I'm working on a WP7 app that uses bing maps to display ~600 pushpins. When i add them to the map using map.Children.Add(pushpin) the UI freezes for ~200 ms. I've seen that in silverlight you can use Microsoft.Maps.EntityCollection to add pins to a map but unfortunately I couldn't find how to use the assembly on WP7. Does anyone know a solution to this?
Maybe you're looking at the problem the wrong way round. WP7 is a compact (though powerful) that excels at showing the user what they want to know quickly (when the apps are written properly).
The user can't possibly see 600 pushpins in one go on a device that small, so why not just show them pushpins that are in the viewable area (or close to it) and add pushpins as the user pans around the map?
Alternatively you could "trickle" feed the pushpins by adding them one (or more) at a time using the DispatcherTimer so that the user sees pushpins being gradually added without drastically affecting performance.
Another possibility (which is what I usually do) is to add a MapItemsControl with the DataTemplate set to a Pushpin and to bind the collection to your collection of pushpin locations. If the binding is to an ObservableCollection you can "trickle" feed it as mentioned above if perf is an issue.
In a viewpoint similar to Derek's, I find it highly unlikely that you seriously want to put 600 pins on the screen at the same time. I'm guessing that they span a large geographic area and the user is unlikely to see more than a handful at a time.
If this is the case, you can trivially apply a cliprect to cull your points, then add the resultant modest list to a layer, and Presto! High performance.
In addition, there is the issue of what to do when the user zooms a long way out, bringing so many pins into view that they merge into one big useless but brightly coloured blob. This is a more complex problem traditionally solved with a quadtree, and I have a suspicion that you just said "a what?" but luckily Google is your friend.
Oh, and to address your stated problem - don't add the pins directly to a map. Add them to a MapLayer and then add that.
Related
I need to display many markers on a WPF image. The markers can be lines, circles, squares, etc. and there can be several hundreds of them.
Both the image source and the markers data are updated every few seconds. The markers are associated with specific pixels on the image and their size should be absolute in relation to the screen (i.e. when I move the image the markers should move along with it, but if i zoom in, they should take the same space of the screen as before).
Currently, I've implemented this using the AdornerLayer. This solution has several problems but the most significant one is that the UI doesn't fare well under the load even for 120 such markers.
I wanted to ask what would be the best way to go about implementing this? I thought of two solutions:
Inherit from Canvas and make sure it is invalidated not for every
added marker but for a range of markers at once
Create a control that holds an image and change its OnDraw to draw all the markers
I would appreciate some pointers from someone with experience with a similar problem.
Your use case looks quite specialized, so a specialized solution seems in order. I'd try a variant of your second option — extend Image, overriding its OnRender method.
I'm trying to write an CAD-like application in WPF(.NET 4.0) that needs to be able to display a lot of 2D points/lines. It will be used to display CAD-plans of entire cities with zoom, pan, rotate and point snapping on mouseover.
Right now I purely use WPF. I read the objects from the CAD file draw them into a StreamGeometry, use it as stroke of a new Path and add it to a Canvas, with several transforms.
My problem is that this solution doesn't scale well enough. It works fine with small CAD-files, but when I want to display like half a city(with houses and land boundaries) it is very very delayed.
I also tried to convert my CAD-file to an image, but
- a resolution a 32000x32000 is sometimes not enough
- when zooming out the lines are too thin.
In the end I need to be able to place this on a Canvas(2D/3D) as background.
What are my best options here?
Thanks,
Niklas
wpf is not good for a large 3d models. im afraid it is too slow. Your best bet is direct 3d or openGL
However, even with the speed of direct3d,openGL you will still need to work out how to cull as many polygons/vertices as possible before the rendering of the scene if you are trying to show an entire city.
there is a large amount of information on this (generally under game development)
there are a few techniques including frustrum culling, near and far plane culling.
also, since you probably have a static scene you may be able to use binary spacial partitioning.
As I understand the subject is 2D CAD system within WPF.
Great! I use it...
OpenGL and DirectX are in infinite loop OnDraw always. The CPU works all the time.
WPF/Silverlight 2D is smart model.
Yes, total amount of elements (for example, primitives inherited from Shape) must be not so much. But how many?
I tested own app (Silverlight). WPF will be a bit faster I hope...
Here my 2D CAD results. Performance is still great. Each beam consists of multiple primitives.
Use a VirtualCanvas like this one from Chris Lovett.
In my WPF app I have a control representing a pack of 20 cards (each about 150x80 px) that fan out in an arc, so they're all slightly overlapping in the centre of the arc. When the control is added there's an animation to fan them out.
After that, the fan/control can be moved around, and when the user hovers over a card it expands and then goes back to normal size when they move off it.
This all works fine, but has a noticeable effect on performance- everything is very jerky, presumably because when other things move all the overlapping stuff and transforms in the control are being constantly recalculated/redrawn.
Any suggestions for how I can improve performance while still keeping individual cards in the fan responsive?
To find the source of the slowdown you need to profile.
Try to find out whether or not WPF is switching back to software rendering or not.
After that try to run on a different computer with other (better) hardware/graphics card.
If it doesn't get any better there might be errors in your app.
I'm currently using the Silverlight Map control for WP7, and am trying to visualize driving directions on the map. In order to highlight the route needed, I am using a MapLayer with a MapPolyline. The problem is that even with CacheMode set to BitmapCache, the MapPolyline area gets redrawn whenever the user pans or zooms the map. I've used other controls such as Ellipses or Pushpins, and with BitmapCache on, none of them redraw and give the same performance hit as MapPolyline.
Here's a quick example
<maps:Map ZoomLevel="3">
<maps:MapPolyline Name="line" Stroke="Red" StrokeThickness="9">
<maps:MapPolyline.CacheMode>
<BitmapCache/>
</maps:MapPolyline.CacheMode>
<maps:MapPolyline.Locations>
<maps:LocationCollection>
<geo:GeoCoordinate Latitude="33" Longitude="33"/>
<geo:GeoCoordinate Latitude="36" Longitude="33"/>
<geo:GeoCoordinate Latitude="33" Longitude="36"/>
</maps:LocationCollection>
</maps:MapPolyline.Locations>
</maps:MapPolyline>
</maps:Map>
If you set App.Current.Host.Settings.EnableRedrawRegions = true; you can see the redrawing that occurs. The performance is particularly bad when you have a larger polyline and zoom in closer.
Is there anything that can be done to help? The native Bing Maps has pretty smooth route drawing, so I would think that there should be a way to solve this?
Thanks!
Can you explain a bit more what the problem is?
I've got an app - RunSat - in which I draw polylines with several hundred points (e.g. I just looked at a 3 hour long bike ride) and this draws fine - including during zoom operations.
I don't understand the problem - even using the sample code above. To help - are you testing on a phone or on the emulator?
As for CacheMode and BitmapCache, I'm really not sure about using these settings for the map - I don't use them in RunSat if that helps - I just leave the phone alone to work out its own GPU drawing.
I have an app that creates a variable number of ScatterviewItems based on which tagged object is placed on the surface table.
The ScatterViewItems are added programatically to the ScatterView based on info looked up in a DB
The Scatterview does a good job of displaying this info
However, I would like them to be
evenly distributed across the table and
not have any items overlapping
Any ideas how to do that?
Sounds like you need collision detection.
There's two parts to this problem: detection and resolution. Detection is seeing if any item's bounding intersects with any other item's bounding. If the items are retangular or circular this is pretty straightforeward. It can get complex if you're dealing with other geometries.
Resoltion is what to do once you've detected a collision. Google will help you find the myriad algorithms for this. Here's a couple links to stackoverflow discussions: WPF: Collision Detection with Rotated Squares, Applying Coefficient of Restitution in a collision resolution method, Best way to detect collision between sprites?.
You can implement collision to work so that items bound off of each other as they scatter. Depending on the number of items, this might cause so much collision that the items don't scatter well. If this happens, just run the collision detection one items have stopped moving.
UniformGrid ?
You can also create your own panel by iheriting from Panel.
You will find some uber-valuable info in the Dr. WPF ItemsControl How-To series : http://drwpf.com/blog/itemscontrol-a-to-z/
That's a must-read, period.
ScatterViewItem has properties Center and Orientation which you can use to programmatically position items. If you know the size of each item you should be able to use these properties to position them in whichever way is ideal for your situation. By hooking into the Loaded event of each and checking ActualWidth/ActualHeight, you can get the dimensions. If you can use a fixed initial size for all of your SVIs, that's even easier.
You could lay them out by calculating a simple grid (plus some randomness to make it look more natural), or you may be looking for what's called a "force directed layout", which gives each object a repellent force relative to its size. After a while the elements will naturally be evenly spaced from one another, though they may still overlap if they run out of room. I haven't seen a WPF example of this, but see flare.prefused.org/demo (layout > force) for what I mean in Flash.