.NET Forum / Windows Forms / Drawing / July 2005
How to draw with a PEN ?? Please help
|
|
Thread rating:  |
expertware@libero.it - 25 Jul 2005 15:45 GMT I need to draw with a pen using a semitransparent color as in the following example:
Dim Color As Color = Color.FromArgb(100, Color.Blue) Dim pen As New Pen(Color, 1) Graphics.DrawPolygon(Pen, Points)
however I get a solid line (the alpha channel is ignored by the pen). Can anyone suggest how to draw my POLYGON with
Color.FromArgb(100, Color.Blue)
and NOT with:
Color.FromArgb(255, Color.Blue) as the pen does?
Or maybe is there an alternative instruction which uses a brush instead of a (solid) pen?
Thank you very much!!
Scott McChesney - 25 Jul 2005 18:38 GMT You can create a Pen from a brush - it's just another constructor. However, you can't draw with a Brush - you can only fill with them. So you can't do something like:
Dim br as New SolidBrush(Color.FromArgb(100, Color.Blue)) Graphics.DrawPolygon(br, Points)
But you *can* do something like this:
Dim br as New SolidBrush(Color.FromArgb(100, Color.Blue)) Dim p as New Pen(br) Graphics.DrawPolygon(p, Points)
Note that the composition of the brush can affect how the Pen draws. MSDN states that lines are drawn "as if they are filled rectangles, with the characteristics of the Brush object." That's not likely to affect you here (I'm assuming you would use a standard SolidBrush, since it supports an Alpha component just fine), but for pens created from TextureBrush and LinearGradientBrush, it can make a difference.
Having said all that, I'm wondering what kind of effect you're looking for. A quick test on my machine shows that a pen created from your example does draw the polygon lines considering the alpha component. It's a little hard to see, given that the pen width is only one pixel, and I'm sure that affects the alpha routine. But it seems to work for me...
- Scott
> I need to draw with a pen using a semitransparent > color as in the following example: [quoted text clipped - 16 lines] > > Thank you very much!! James Westgate - 25 Jul 2005 22:20 GMT Check that graphics.CompositingMode is set to the correct setting. Also, if you are drawing onto a plain white background you will just see a lighter blue.
James
 Signature Create interactive diagrams and flowcharts with ERM Diagram at http://www.crainiate.net
Take the ERM Tour at http://www.flowchartcontrol.com
> I need to draw with a pen using a semitransparent > color as in the following example: [quoted text clipped - 16 lines] > > Thank you very much!! expertware@libero.it - 26 Jul 2005 07:31 GMT Dear Scott and James,
Thank you very much for your suggestions. I have tried the Scott method (which actually I tried before) both using Graphics.CompositingMode = Drawing2D.CompositingMode.SourceOver
Graphics.CompositingMode = Drawing2D.CompositingMode.SourceCopy
In the first case the lines are still drawn with alpha=255 and in the second case they are white (on a white background). I have made a web page with the picture I get using:
Graphics.CompositingMode = Drawing2D.CompositingMode.SourceOver Dim br As New SolidBrush(Color.FromArgb(100, FacesBrush.Color)) PenUsatoPerSpigoli = New Pen(br) Graphics.DrawPolygon(p, Points)
as suggested by Scott. Here is the result:
http://cam70.sta.uniroma1.it/TechnicalPreview/scott.htm
as you see, while the faces are semitransparent, the edges are drawn with a alpha value different from that used by for the faces (although the brush is the same).
I need the edgest to be colored the same way as the faces (faces use a brush with A=100) !! Any suggestion?
Thanks you very much!!
Pamela
Scott McChesney - 26 Jul 2005 15:05 GMT Pamela -
After doing some tests, here's what I believe the issue is.
Your lines are not being drawn with an alpha of 255. What's happening is that, since you are drawing over your filled shapes, the alpha-100 pen is blending with the alpha-100 background and creating a color somewhere between alpha-100 and alpha-255. Note that, if you draw your polygons and then fill them, you will get lines that are closer to your fill color. But it still won't be the same. I'm assuming you're filling first because your output matches my tests when I fill first.
Changing the CompositingMode doesn't help. In fact, if I change it to "SourceCopy", I get even worse results - the lines are drawn even more starkly. However, the description of "SourceOver" seems to confirm what I'm talking about above - the color of the pen will be blended with the background based on the alpha component of the pen.
I guess I look at it this way: you are drawing your lines, presumably, because you want to see them - right? So, in essence, you are getting what you want. If you don't want to see the lines, then don't draw them. Anything you try to do, since you are drawing over your alpha-blended background, is not going to get you what you want - the alpha components of the two objects will interace with each other, and you'll get what you're getting. unless you create your pen with an Alpha of 0, which would be a waste of time.
If you want the edges of your shapes to be defined in some fashion (which is what I think you're really going after), then you'll have to create a new polygon consisting of *only* your edge points, and draw that. Since you want it defined for the user, I would think that what you're getting with the pen you're using will work just fine (with the suggestion that you may want to use a slightly thicker pen to get a bit more definition.) I also believe that a polygon is not going to be the best thing for you in the end - I think you'll want to investigate using a GraphicsPath to draw your edges. But I may be wrong on that point.
HTH
- Scott
> Dear Scott and James, > [quoted text clipped - 33 lines] > > Pamela expertware@libero.it - 26 Jul 2005 18:14 GMT Dear Scott,
thank you very much. Your analysis is enlighting. As I understand there is no way to eliminate the problem if I draw the edges.
Actually I would be happy to avoid drawing the edges (which slows down), but the essential reason why I am doing it is that, if I don't, between the faces you can sometime see a thin white line (due to rounding I guess), which is *very* ugly.
To show this problem , I have placed a picture for you (or any other interested) here : http://151.100.3.84/technicalpreview/scott.htm
So back to the problem. How can I get this doughnut transparent and at the same time not having those ugly white spaces between faces? It would seem an elementary issue.
By the way, faces are done simply with this instruction: Graphics.FillClosedCurve(FacesBrush, .Points)
Thank you,
Pamela
Frank Hileman - 26 Jul 2005 19:00 GMT Hello Pamela,
You can get often remove the white lines by turning off antialiasing on the Graphics (SmoothingMode.None). However, now the edges of the faces will no longer be antialiased. There is no general solution to that problem except to draw all faces at once with a single polygon instead of multiple polygons. Looking at your image, this might be difficult.
If the faces are not transparent, but solid, you can sometimes eliminate the white lines by overlapping the faces slightly. In this case you can leave the antialiasing on. If you overlap transparent faces, you will sometimes see a darker line at the border.
These are limitations of GDI+.
Regards, Frank Hileman
check out VG.net: http://www.vgdotnet.com Animated vector graphics system Integrated Visual Studio .NET graphics editor
> Dear Scott, > [quoted text clipped - 22 lines] > > Pamela Scott McChesney - 27 Jul 2005 04:22 GMT Pamela -
I'll defer to Frank's much more extensive knowledge in this area. But I can provide some information about why you are seeing what you're seeing - at least, what I think is happening - as well as my own suggestions.
When filling a rectangle, GDI (and GDI+) doesn't consider the bottom and right sides of the rectangle. The algorithm, as I understand it, is defined such that the area of the rectangle includes the top and left sides, but not the bottom and right sides. I don't know what your matrix of points looks like, but given what you're doing, I would guess that you're essentially working with rectangles that are "twisted" through various transformations into the shapes you need for each section. Given that, this algorithm is going to come back and bite you.
You might try modifying the edge-drawing code to only consider the "right" and "bottom" portions of your edges, since it appears to be your "left" and "top" edges that are giving you fits. I don't know whether this is possible, and even if it is, it makes for a bunch of ugly DrawLine code. The definition of "right and "bottom" may not be intuitively obvious from the transformations you do, especially given that you need to generalize the determination. It also adds even more time to the rendering operations, since once you've twisted your rectangle, you have to examine all points to find the right and bottom sides. While you could theoretically save some time in the drawing phase - you're only drawing half the lines, after all - I don't know whether that would offset all the additional polygon calculations. Outside of that, Frank's suggestion of one massive polygon is about all I can offer, and I would heartily agree with him that that's a tall order.
Frank - would employing a GraphicsPath that contains all the polygon edges to draw be a possible solution?
- Scott
> Dear Scott, > [quoted text clipped - 22 lines] > > Pamela expertware@libero.it - 27 Jul 2005 07:59 GMT Dear Scott and Frank,
Ok we have established that even 2 poligon have a common side (they share the point) when you fill them a thin white space can appear (if the common side is not vertical or horizontal) due to the nature of the filling algorithm and the antialising algorithm.
You both suggest to build a unique polygon and the fill it.
perhaps doing something:
for each face in faces path.AddPolygon(.Punti2DFaccia) next face
Graphics.FillPath(Brush, path)
This would be very nice. However at this point we have another problem Each face has its color. Since to the chart there attached an arcball controller, I do real time shading so each face has a different color (based on the angle of a light vector with the face).
In addition before drawing the faces (since, as you see, the charts can be made of slices) the faces are sorted. The sorting is such that the faces more distant from the eye are drawn first.
It seems we cant have a unique poligon since different faces have different color and can come in any sequence.
Still I am surprised about the difficulty of accomplishing something which would seem an easy task. It seems strange to me that if the fill algorithm in GDI+ has this problem, it has not be solved so far. It is more likely we are missing something...
If useful I can provide more information about the contruction of these pictures and code. However it is nothing fancy. Just an ordinary matrix of points and a list of faces. The faces can be formed by any number of points, depending on the picture. For each faces the points are listed clockwise so that the angle with visual and light can be computed consistently. Faces are shaded proportionally to the cosine of the angle with the light. All common graphics methods.
PS Frank suggestion about overlapping seem to work only for solid, but if we are not using transparency there is no problem at all. Drawing the edge would just solve any problem If on the contrary we are using transparency, overlapping has the same alpha interaction problem plus the fact that you loose accuracy in the drawing and you have an enormous difficulty on how to compute the the overlap, since the face can have any angle.
Scott argument about top left right bottom is not very clear to me. In general we deal with polygon not just rectangles. So if there is a filling criterion I feel it should be general not just for rectangles.
Thank you !! Pamela
Scott McChesney - 27 Jul 2005 11:55 GMT Pamela -
I would assume that the filling of shapes - rectangular or otherwise - is the same within GDI+, though I've never tested it. And after I look at your original image, I'm re-assessing whether my thoughts on the fill algorithm are really the problem anyway. Given how your polygon matrix is defined, the fact that certain sides are not filled should be covered by the fact that they lay next to sides that will.
To try and simplify what I was talking about, if you fill a rectangle, the left and top borders of said rectangle will be drawn as part of the fill, but the right and bottom borders won't. Though you may not necessarily have a single right or bottom border to your polygon, I would assume that filling a polygon would work similarly. It all depends on whether a "right" and "bottom" can be determined, I suppose.
If I may ask: are you doing this entirely within GDI+? Given what you're trying to accomplish, it would seem that DirectX would be ideally suited for your task. Perhaps it's too late to change gears that drastically, but DirectX was written to handle the kinds of drawing you are doing, and it's going to be accelerated (which GDI+ is not). You likely won't have this issue of polygon boundaries, and it can handle the real-time shading and shape rotation fairly easily. Maybe you looked into that route already and discarded it...
- Scott
> Dear Scott and Frank, > [quoted text clipped - 67 lines] > > Pamela expertware@libero.it - 27 Jul 2005 13:06 GMT Dear Scott,
Thank you for your generous contribution. This is a VB.NET project. So the GDI+ came as natural choice. All code is simple VB.NET and GDI+ and ALL pictures (3Dhistogram, Pie, Doughnut, 3dStrips...) are made with a unique simple face generator. We don't need the speed of a videogame and the purpose of these charts is to be enclosed in reports. We have attached an arcball controller (that is the scene rotate with mouse in any direction), and even doing real time shading the animation is smooth even with a huge number of polygons (for instance a smooth torus). For this reason using directX has been considered a useless complication, which would (probably) complicate development and web publishing. But I welcome advice if anyone thinks that it is worth turning to directx (??)
Also i guess it would have just the same problem, since fill algorithm are well known and established, and probably just the same. Here the problem is strictly related with transparency, filling and overlapping.
I think the only effective and general way to deal with this problem is giving the user the possibility (when editing the chart) to modify the alpha channel separatly for both faces and edges. So that he/she can tune the opacity of the edges until it maches the faces. I have done some experiment and it seems to be satisfactory.
Unfortunately there is not a deterministic formula which link the opacity of the faces with that of the edges, and must be tuned manually.
If you or any other wish to continue supporting me and this program with your enlighting suggestions there is an interaction website and supporting people will be publically acknowledged and awarded with a lifetime licence of the final product. The site is: http://cam70.sta.uniroma1.it/TechnicalPreview/
If you or other readers join and occasionally provide some advice, I would be happy.
If you or any other in this newsgroup finds a clean solution to the original problem (avoid the thin spaces which can occur between 2 filled adjacent regions) please let me know at any time so that I can implement it.
Thank you very much!!!
-Pamela
Scott McChesney - 27 Jul 2005 15:07 GMT Pamela -
DirectX isn't necessarily just for videogames. Obviously, that's its main function, but it works well for almost any complex graphic operation that requires shading, rotations, and so forth, at decent speeds. And while you could assume that the same problems you see in GDI+ appear in DirectX, I don't think so. It's not a guarantee that DirectX uses the same fill algorithms as the standard Windows libraries, and given that DirectX is all about assembling polygons into composite shapes, I imagine this issue has probably been resolved there.
Given where you are in your development process, and the fact that you're considering web publishing, I'd probably skip DirectX. I don't know how well it would integrate with web pages, and you'd obviously have to have it installed on your web server(s). Plus, it's probably going to be quite a change to your programming model. Yes, this should be a simple task for GDI+, but the .NET drawing library wasn't really built for 3D modeling - that's what DirectX is for. :-)
- Scott
> Dear Scott, > [quoted text clipped - 52 lines] > > -Pamela Frank Hileman - 27 Jul 2005 18:09 GMT Hello Pamela,
I have another idea. It is complicated. Remember that slightly overlapping edges do not show the white space, when using a solid brush.
There is a way to use a solid brush and still make your fill translucent. Take the overall set of shapes which must be transparent (the front faces) and draw them into an intermediate Bitmap using a solid brush. Then transfer that bitmap to your buffer or output Graphics using a ColorMatrix to render it partially transparent. I believe Bob Powell's site has some info on using a ColorMatrix that way.
The disadvantage: you must have the same alpha value for all the front faces. Also the overlapping bit can affect the edges slightly.
Regards, Frank Hileman
check out VG.net: http://www.vgdotnet.com Animated vector graphics system Integrated Visual Studio .NET graphics editor
expertware@libero.it - 29 Jul 2005 09:34 GMT If I understand well your suggestion. You are proposing:
- Just make the chart with 100% opacity, no transparency - Then process the graphic object to make transparent.
I can see 2 reason why this cannot work (but I may be wrong):
1. If have already drawn a solid chart, the hidden colored faces cannot interact with the visible face, as it happens with when you draw with transparency. Applying transparency afterwards does not make the desired chart.
2. On the same chart there are items with different degree of transparency. For instance you can have a coordinate system with opacity 200 (of 255) and plane XY lightGree, Planes XZ, YZ, azure. This is my case. And over the coordinate system a 3D istogram with different color poliedra. Sometimes (depending on rotation angle) a plane is completely visible, some other partially hidden by poliedra.
No, I think we must go back to the filling algoritm and if a solution is theoretically possible it should be find there.
Since Scott talked about DIRECTX I would like to ask here (hope anyone is using it) Does it have the same problem when drawing * transparent * faces??
This is an important issue, because if it does not it means that the FILL routine used by GDI+ is lousy and we might override with a routine written by ourselves...
But I am beginning to think that this is a limitation shared by any graphic environment since for having things smooth and nice you need antialising at the edges. At the same time, however, if the edges are not solid but transparent, they are going to interact. So you either get a white space or a transparency degree (lower) which is different from that of faces.
I would like to hear from people who have experience on * transparency * on other platforms, to see how this issue is dealt with.
Pamela
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|