Coordinate mapping problem in GDI
Ali
When we develop the drawing program, it is inevitably encountered the problem of coordinate maps, and this is precisely a very hurtful brain, and it will not understand the problem. I often have a few hours, hate, and finally have a day of heart, open a weekend, and smash all the information obtained, especially the general MSDN, found related issues. One corner of the iceberg, but it has already been suddenly a sense of sudden feeling, and it is also hoped to have a little help from all the people who are troubled by the same problem. At the same time, they also hope that the men must not be because of this. A simple problem dismissed.
The first thing to be clear is that the coordinates used in the plot statement are always the coordinate value of the logical space, and the destination we finally draw is Physical Device Space.
1. Preparatory knowledge: four coordinate spaces (or coordinate systems) specified in GDI.
1.1 World Coordinate Space: The purpose of introducing the World is to pan, zoom, shear, etc., the maximum coordinate range is 2 ^ 32 units, 2 ^ 32 unit wide, the X-axis is forward when the initial state is Right, Y axis is forward. World coordinate space can be a logical space.
1.2 Page Coordinate Space: When there is no World, it is logical space, and this is the most common. The maximum coordinate range is 2 ^ 32 units high, 2 ^ 32 units wide, and the x-axis is forward to the right when the initial state is forward, and the Y axis is upward.
1.3 Device Space: The equipment space is a conventional destination for coordinate transformation. The maximum coordinate range is 2 ^ 27 pixels, 2 ^ 27 pixels wide. It is characterized by the X-axis forward to the right, the Y axis is downward, the origin is in the upper left corner of the physical device, and these rules can not change.
1.4 Physical Device Space: This space represents a specific physical device. It is the coordinate space we can see. It is also the final destination of graphics. We draw a large size graphic to make us see how much, completely depend It's a size. It can be a client area of a Windows window, or a whole desktop, or a page of a printer, or a page paper of a plotter.
Figure 1 Coordinate mapping process
2. From the perspective of the Windows system, look at the GDI coordinate mapping.
First we look at how the coordinate map is made from the perspective of the Windows system, or to see how Windows converts the logical spatial coordinate value we used in the program into physical device space coordinate values. It is usually divided into three steps.
Step 1, World Space → PAGE Space. If the programmer uses the SetWorldTransform function to explicitly define the formula of the World Space to the Page Space, Windows will make this mapping, the specific rule is defined by the setWorldTransform function, and the logical space at this time is World.
If the setWorldTransform function appears, Windows will not perform the WORLD space to the page space mapping, and the Page Space to the Device space map, the logical space at this time is Page Space.
In fact, the World Space is only introduced in Windows98, and we generally don't use it. But if we want to show the logical space in a "distortion" manner, the World coordinate space is a very good tool.
Step 2, Page Space → Device Space. This is a mapping step for our programmer's most concerned, and the mapping rules are:
Among them, Di represents the device spatial coordinates of the X or Y direction, and the unit is pixel; Li represents the PAGE coordinates of the X or Y direction, and the unit is a logical unit (ie, own definition);
L0 represents the coordinate value of the origin of Window in the PAGE space, and the unit is a logical unit;
WE indicates the width (height) of Window, determined by the SETWINDOWEXTEX (W, H) function, and the unit is a logical unit.
VE indicates the width (height) of ViewPort, determined by the SetViewPortextex (W, H) function, and the unit is pixel.
D0 represents the coordinate value of the origin of ViewPort in the Device space, the unit is pixel.
I don't quite understand it, I don't need to worry, because we don't need to worry about this formula, let Windows hurt, but the basic principle we still have to understand, so that we have a deeper understanding of the coordinate map, this is what I write it out. the reason.
Step 3, Device Space → Physical Device Space. This mapping follows one-on-one principle, a pixel of the Device space is a pixel of the Physical Device space, and their coordinate origin is in the upper left corner of the physical device, the coordinate direction is the X-axis forward to the right, the Y axis is forward Next, remember is down! . The rules of this map Our programmers cannot change, this is the so-called device independence. For example, we have to draw a PHYSICAL Device, we don't want to manage this customer area, how to display it, we only need to use the corresponding Device space as "canvas", in this Output on the canvas is OK, and other work is completely automated by Windows.
3. From the programmer's perspective
The coordinate map is to construct a logical space that meets the requirements according to the requirements of its actual problem. The so-called satisfaction requires that each of our programs can appear on the corresponding position we expect on Physical Device. Since Device Spaces to the Physical Device space is a one-to-one mapping, we can completely see the drawing destination into the Device space, and the logical space constructed is only necessary to correctly map to the Device space.
3.1 Page Space → DEVICE Space
If we don't use world space, the logical space at this time is Page Space. Let's see how to determine the three elements of it: unit scale, direction, origin.
First, use the SetMapMode (int) function to select the mapping mode. There are 6 kinds of prior defined patterns, which can be used directly, such as MM_HIMETRIC mode indicating that the unit scale of the PAGE is 0.01 mm, the x-axis is right, the Y axis is forward, the origin and the Device space The origin coincidence. If there is a line segment of 10 in the program at this time, then in the eyes of the programmer, this is a line segment 10 × 0.01 = 0.1 mm, regardless of the use of multiple resolutions, it is so long, we can even use rule Try it on the screen. If you choose a predefined mapping mode, it is equivalent to Microsoft to construct the Page space for us. The following things we don't have to do it.
But many times, Microsoft's things are not necessarily suitable for us. At this time, set the mapping mode to m_isotropic or mm_anisotropic, and use the following four functions to define our own coordinate system:
Setwindowext (int Lwidth, int Lheight) // parameter unit is logical unit (logical), if the parameter is negative, indicating that the corresponding coordinate axis of Window is opposite to the PAGE space. The unit of SetViewPortext // parameter is pixel (Pixel), if the parameter is negative indicates that the corresponding coordinate axis of ViewPort is opposite to the Device space.
Setwindoworg (int LX, INT LY).
SetViewPortorg (int PX, INT PY).
These four functions present two new concepts: Window and ViewPort, which correspond to the Page space and Device space, but please don't be right. The purpose of introducing their purpose is to determine the unit scale, direction, origin of the PAGE space.
1. The unit scale of the x-axis = | PWidth | / | lwidth |.
This means that a logical unit on the X-axis is equal to how many pixels. The following example is explained.
For example, let's get how many pixels per inches across our monitors through getDevicecap (logpixelsx), set to P, and then we assign it to PWIDTH, assignes lwidth into 2, that is, pWidth / lwidth = p / 2. So, at this time, the unit scale on the X-axis is p / 2 pixels; it is also because P pixels represent one inches, so the unit scale on the PAGE X-axis at this time is also half an inches.
Note this example, although the X direction "range" of ViewPort is P pixels, but the "range" of the Device space X-axis is not only P pixels, but 2 ^ 27 pixels, as for the visible range to the end What is, it depends on the physical equipment space.
2. The direction of the x-axis: This is determined, and the LWIDTH is in the same number of PWIDTH, then the X-axis direction of the PAGE is the same as the DEVICE space X-axis direction, otherwise it is reversed.
3. origin. This is a bit of trouble, we need to overlap Window with ViewPort, including origin and coordinate axis direction, and then determine the origin of the PAGE. The following describes an example.
Example: Suppose we construct a Page space by the following statement:
Setmapemode (mm_anisotropic);
Setwindowext (10, 100);
Setwindoworg (0, -100);
SetViewPortext (20, 200);
SetViewPortorg (0, -200);
Figure 2 Example of page space mapped to Device space
(Since 100 logical units are equivalent to 200 pixels, I draw them in the same length.)
From these statements, we can quickly determine the unit scale of the PAGE space (such as the Y-axis per logical unit 200/100 = 2 pixels), and the direction of the Y-axis is the same as Device space (100 and 200 in the same number), but Where is the origin of Page? Please see:
First we draw a Window coordinate system in the PAGE space, draw a ViewPort coordinate system (as part of Figure 2) in the Device space. Then, since the Window coordinate direction in the example is in contrast to ViewPort, it is also necessary to flush the PAGE space (see the middle portion of Figure 2). Finally, the Window is overlapped with ViewPort (see Figure 2), so that their origin and coordinate direction are consistent. At this time we can clearly see that the origin of the PAGE corresponds to the origin of the Device space, and the direction is also the same. Through the above 1, 2, 3, we can completely determine the Page space suitable for our own requirements. When we don't want World, it is logical space.
There is another question to pay attention to the difference between MM_anisotropic and MM_ISOTROPIC. For the former, the unit scale of the X direction can be different in the Y direction (of course, the same may be the same), but the unit scale of the latter X direction is identical to the unit scale in the Y direction, if it is calculated by calculating Window and ViewPort The range ratio is different from the unit scale values in the two directions, and will be subject to the smaller one.
3.2 World Space → Page Space
Sometimes we need to display a circle or what graphics from a tilt angle, but when we use the drawing statement, we still want this round to consider the problem in this round, because there is only this, we are constructive Thinking is not confusing, how to achieve it? You can achieve this by adding the world. Since this map is generally used, I am here only a simple explanation with an example.
Void csampleview :: DrawShearcircle ()
{
CClientDC DC (this);
Dc.setmapMode (mm_anisotropic); // Mapping mode is set to an anisotropy.
// The following statement sets the minimum scale value of the PAGE space to 1 mm, the origin is located in the center of the client area, X forward, and forward.
Dc.SetWindowext (1, -1);
INT PPERMMX = DC.GetDeviceCaps (Horzres) / DC.GetDeviceCaps (Horzsize);
INT PPERMMY = dc.getDeviceCaps (Vertres) / DC.GetDeviceCaps (Vertsize);
Dc.SetViewPortext (PPERMMX, PPERMMY);
CRECT CR;
GetClientRect (& CR);
Dc.SetViewPortorg (cr.right / 2, cr.bottom / 2);
Dc.SetWindoworg (0, 0);
// The following statement sets the WORLD space to the mapping rule of the PAGE, which will generate a shear of a Y-axis.
SetgraphicsMode (DC.getsafeHDC (), GM_ADVANCED); / / must first open GM_ADVANCED.
XFORM XF;
XF.EM11 = 1.0;
XF.EM12 = 1.0; // The shear constant in the Y-axis direction is 1.0
XF.EM21 = 0.0; // The shear constant in the X-axis direction is 0.0
XF.EM22 = 1.0;
Xf.edx = 0.0;
Xf.edy = 0.0;
SetWorldTransform (dc.getsafehdc (), & xf);
Dc.Rectangle (-50, 50, 50, -50); // The center of this rectangle is at the center of the customer area, with a length of 100 mm. However, since the World is set, although it is a square from the statement, it is actually displayed by a diamond of 45 °.
Dc.ellipse (-50, 50, 50, -50); // Despite the view from the statement is a circle, but actually displayed is an ellipse. }
4. Conclusion
The above is just some of my immature opinions, if there is something wrong, I hope to discuss the letter: alialili@163.net