I am not quite sure about the differences between the classes System.Windows.Media.Drawing and System.Windows.Shapes.Shape. They both expose functionality related to 2D graphics in WPF. When would you choose one in your WPF application, and when would you choose the other?
A Shape inherits from FrameworkElement and is therefore a high level object which provides features such as hit-testing, styling, layout and data binding. In contrast a Drawing does not inherit from FrameworkElemet and doesn't support any of these features. As the documentation mentions a Drawing is useful for lightweight visual objects. If you are creating a complex brush to use to paint areas or a background a DrawingBrush would be very efficient.
Drawings can combine text, video, images and Geometry objects (another light weight class) to create complex but very efficient and fast drawings.
In short a Drawing is a low-level alternative to a Shape.
As for use cases, it depends.
If you have to animate or do any sort of binding you would use Shapes.
If you are creating brushes or complex clip arts/vector graphics you would probably use Drawings.
Also, if you draw things by overriding OnRender you would mostly use Geometries.
A Drawing is also Freezable and can thus be shared among threads (assuming it is frozen).
Related
I am working on a Chart Control,
I need to implement the Chart Snapshot feature for capturing a vector based image in high quality of Curves and Texts, in any requested size.
Can anyone suggest me any solution or a pointer to resolve this problem.
Any kind of help in deeply appreciated.
If you have to save your image in a vector format you can using tracing. Potrace is an open source bitmap-to-vector tracer library (but considers that bitmap tracing is imperfect). Also considers that wpf is linked closely with XAML, a vector graphics markup languages, so you may want convert raster graphics to XAML (though Charles Petzold you can't embed a bitmap in a XAML file)
If you need to draw a vector image you can use the Shape element that provides a base class for shape elements, such as Ellipse, Polygon, and Rectangle; and add the shape as Panel child. If you are dealing with thousands of shape I suggest to use the DrawingVisual class, a visual object that can be used to render vector graphics on the screen, and its RenderOpen method.
To zoom you have to work with transformations, in particular ScaleTrasnform and apply the transformation to your panel or to your shapes.
Hope this help.
You can take a look at XamlToy but I have not already try it.
http://xamltoys.codeplex.com/
I am developing a Maps like application using WPF. I have ~10,000 PathGeometry, Shapes added to the canvas. I have added ScaleTransform and TranslateTransform for zooming and panning controls.
The problem I'm facing is, when I zoom or pan, there is slight lag. Is there a way to organize the data so that I handle only the Shapes that are visible?
Any hints on making it more efficient will be helpful and appreciated.
What kind f stuff are you putting on the canvas? If using pathGeometry, are you enclosing them in Path class? If so, Path has FrameworkElement in its superclass hierarchy, which is responsible for massive performance loss.
Take a look at my question here. Although it is about Shape class, but the reason of performance degradation is the same, FrameworkElement.
If you are doing so, the solution is to use PathGeometry instead, and enclose it in DrawingContext of a DrawingVisual using DrawingContext.DrawGeometry() method.
Here are some links that should help.
Path Geometry
DrawingContext.DrawGeometry()
Optimizing Performance: 2D Graphics and Imaging
And draw the shapes yourself, using combination of lines, and other things provided by classes derived from Geometry class (ArcGeometry, PathGeometry etc).
This should help.
If you want the ultimate in performance for immediate drawing in WPF, then check out WriteableBitmapEx. This is an excellent open source library, which I recently contributed to. it provides GDI-like drawing capabilities on WriteableBitmap and is compatible with Windows Phone, WPF and Silverlight. The API is simple, you get blitting, polygons, lines and simple shapes etc... You won't get datatemplates and gradient brushes however.
What is the best approach to render charts and then save them on a hard drive for further distribution using WPF?
I found a number of ways to accomplish this by using the following types:
DrawingVisual - creating a object of this type and then rendering graphics on its context;
Shape - deriving from the Shape class and then overriding its DefiningGeometry property where the actual rendering is happening;
PathFigure - adding LineSegment-s to an instance of this class and then adding this instance to a Canvas;
Adorner - deriving from it and then overriding its OnRender method;
WritableBitmap - rendering on it and then adding the bitmap to a Canvas.
Of course I'm going to write an app to test how fast each of these will be. But can anybody tell me:
whether am I on the right track?
are there any other means to do such rendering?
which one of them is the best in
terms of performance?
It all depends on your actual usage, in your case you mention saving on the hard drive for "further distribution" - I'm going to assume you are saving them as an image (jpg or png) and not as wpf objects (xaml).
You should consider if WPF is the right tool for the job, WPF is a UI framework and not a generic image processing library, it may be best to use something else entirely for generating images.
For a reasonable number of points your performance bottleneck will be encoding the image and saving it to disk - not actually rendering it - so you should choose the method that is easier for you to code.
All the articles about high performance WPF charts are a: about charts with 10,000 points and more (because that is where the performance problems are), b: about charts you display in your GUI (because otherwise you can use an image processing library to create the bitmap) and c: charts that change all the time (so they work nicely with data binding) - there's a reason why they don't talk about saving charts to disk.
For a very large number of points:
The fastest way to draw in WPF is to inherit from FrameworkElement (not Adorner) and override OnRender.
When the data changes often it is recommended to use multiple DrawingVisual objects because then you don't have to re-render everything when one value change - but this is not relevant for you since the image won't change after you save it anyway.
WritableBitmap is used for raw bitmap access, you use it when you decide to give up on all the nice layout and drawing WPF gives you because you can't take the overhead, if this is the case you should re-read my first point above.
So, to summarize, you are asking the wrong question :-) if you need to save images to disk than either the WPF rendering speed is not your bottleneck or you shouldn't be using WPF to begin with. If you do use WPF just pick whatever is easiest for you to code.
BTW: Adorners are used to display "floating" elements above the normal UI, you can use them for tooltip-like features but not for the main chart rendering (and you probably don't want them at all since your main usage is saving the image to disk), FrameworkElement is the base class you are looking for.
I'd like to ask if there is any possibility to draw on WPF Canvas with some kind of a Graphics type providing methods like: DrawLine, DrawPath etc.. (as it was in .NET 2).
I know there's a lot of stuff like storyboards etc.. but I'm planning to do all the drawing in code behind and to have just 1 Canvas in WPF without any child elements.
Do you think it is a good idea? will it be smooth ?
I'd like to ask if there is any possibility to draw on WPF Canvas with some kind of a Graphics type providing methods like: DrawLine, DrawPath etc.. (as it was in .NET 2).
Yes, you need to use the DrawingContext class
Do you think it is a good idea? will it be smooth ?
That's hard to tell, depending on your exact needs... If the canvas doesn't have any child items, I think a better solution would be to create a custom control and override the OnRender method. Regarding smoothness, it all depends on how you implement it...
Is there any disadvantage of using ModelVisual3D over Model3DGroup. How much can the resource/performance impact possibly be?
ModelVisual3D gives me much more than Model3DGroup does but AFAIK everything that can be done with Model3DGroup can alos be done with ModelVisual3D.
So why not just always use ModelVisual3D?
The answer is Yes. Having many ModelVisual3ds will be orders of magnitude slower than using a Model3DGroup
My understanding is that ModelVisual3D is more akin to a UIElement, i.e. more of a heavy weight object. MSDN says about ModelVisual3d:
"Provides services and properties that are common to all visual objects, including hit-testing, coordinate transformation, and bounding-box calculations."
So if you wanted to 100 clickable 3d objects in your scene you would need 100 ModelVisual3d elements.
Model3DGroup (along with GeometryModel3D) on the other hand is a Model3D - the building blocks of 3d models. A single Model3D can appear as the content for several ModelVisual3Ds. Model3Ds are more lightweight than ModelVisual3D.
If you wanted to construct 3d models from building blocks (like Lego), you could define several GeometryModel3Ds, then combine them together using a Model3dGroup.
Yes, the class naming is horribly confusing, and I don't think the Daniel Lehenbauer sheds any light on the subject for the average human.