I have problem optimizing drawing Google-like map. It works OK for hundreds of points, but when it comes to larger amounts like thousands it gets fuzzy and slow. Also unzoomed it looks weird.
I'd like to know how to optimize drawing algorithm to draw fewer places so it looks like unzooming on Google Maps.
However I also draw links between places, and I can't optimize that.
Please, post anything you can think of, I have to finish this and send it tomorrow.
Here's how it looks like:
zoomed in
zoomed out
Here's two ideas:
Every object that we draw on a map has an extra value in the database, "Zoom Level". When zooming in extra items will be shown based on that value.
A second way to this is to use grouping. If items start to overlap show one point with [10 items]. Only show the items beneath it when zooming in.
I think I would be tempted to not draw lines that are shorter than a threshold (and I mean this in terms of the viewport, not absolute distance terms). That means that when the map is zoomed out, you will have less to draw and the map will look less busy and when the map is zoomed in the lines between these nearby points will become visible. Edit: actually, thinking about it some more, I think I would only apply this length restriction when there are a large number of lines on screen — or make the length threshold a function of the number of lines on screen.
I think I would also be tempted to not draw lines that are from points that are off screen (out of the viewport) or, at least, quite a way off screen (a threshold away from the viewport's centre). I would suggest trying this change first.
These changes may seem like they will be hiding information (and they will) but, as it stands, the map is so busy this information presented is near useless anyway.
some hints:
clip region, to draw points only in the clip region
you can check opensource GIS project, see how they optimize drawing.
Related
I'm currently creating a large map, that consists of a lot of rectangles (33,844), that all have a unique name (label), which I'm drawing on top of them using a SpriteFont.
Drawing all of the rectangles takes no performance hit at all. But, as soon as I try to write all of their labels with DrawString(), my performance goes into the dumps.
In my head, I would like to draw all my rectangles and text to one texture all at once, and only have to keep redrawing that entire finished texture. My issue is, this is an enormous map, and some of the coordinates for the rectangles are very high (example: one slot's x is 14869 and y is 23622), and they're far bigger than a Texture2D allows.
Since this is a map, I really only need to draw the entire thing once, and then allow the user to scroll/move around it. There's no need for me to continually redraw all of the individual rectangles and their labels.
Does anyone have experience with this type of situation?
Try to only render the labels that you can see on the screen and if you can zoom back far enough, just don't render them.
Textrendering is expensive, since it is basically creating a rectangle to draw on for every character in the font and then applying the same RGBA texture to it. So depending on the number of characters you write, the number of rectangles increases. This means four new vertices per character.
Depending on what you write you could simply create a texture with the text already on it and render that, but it won't be very dynamic.
EDIT: I need to clarify something.
There's no need for me to continually redraw all of the individual rectangles and their labels.
This is wrong. You have to draw the whole thing every frame. Sure, it doesn't increase memorywise, but it still is a lot to render and you will need to render it every frame.
But as I said: Try to only render the labels and the rectangles that collide with the screenboundaries, then you should be fine.
There are two ways to solve your problem.
You can either render your map to a RenderTarget(2D/3D) or you can cull the rectangles/text that are offscreen. However, I am not 100% sure that RenderTargets can go as large as you would need, but you could always segment your map into multiple smaller RenderTargets.
From more information on RenderTargets, you might want to check out RB Whitaker's article on them, http://rbwhitaker.wikidot.com/render-to-texture
Culling, in case you are familiar with the term when used in this context, means to only render what is visible to the end-user. There are various ways that culling can be implemented. This does however require you to have already implemented a camera (or some type of view region) and you perform a basic axis-aligned bounding box collision (AABB collision, which MonoGame's Rectangle supports out of the box) of the rectangles against the camera's viewport and only render it if there is a collision.
A basic implementation of culling would look something like this:
Rectangle myRect = new Rectangle(100, 100, 48, 32);
public void DrawMapItem(SpriteBatch batch, Rectangle viewRegion)
{
if (viewRegion.Contains(myRect))
{
//Render your object here with the SpriteBatch
}
}
Where 'viewRegion' is the area of you world that the camera/end-user can actually see.
You can also combine the two methods, and render the map to multiple render targets, and then cull the render targets.
Hope this helps!
I need to arrange tooltips for points that are located on a complex 2D shape.
The tooltips have different sizes
They must not obscure the shape itself
The lines that connect the tooltip to the points should not cross one each other.
The tooltip should be as mush closer to the point it belongs to.
I've tried several searches in google but nothing was close enough to what I need.
You've asked quite a doozy. I haven't personally worked on something like this, another SO member will likely be able to give you a complete solution. However, here are some points to consider when finding your solution.
1. The tooltips have different sizes
You will need a way determining this independently of your shape location algorythm. Performing the re-size as part of step 2 would make things much more complicated and may result in inconsistent behavior. So firstly, look into generating the dimensions of your tooltips.
2. They must not obscure the shape itself
In principle, you want a solution where the tooltip is not 'colliding' 'inside' the complex shape. Looking up '2d shape collision detection' would help here. You will need to know the dimensions of the shape of interest. You can't use a picture of a shape (unless you use a map of some sort). Most algorythms will require the following information for shapes containing concave points:
The points (2d vectors) that make up the complex shape
The points from which tooltips "spawn"
The tooltip dimensions (see point 1)
3. The lines that that connect the tooltip to a point should not cross eachover
This makes the problem significantly more complicated because it implies that multiple tooltips generated by #2 may be visible at the same time which will introduce alot of complexity.
Now you have N tooltips which need N locations occupying different areas which may not overlap, collide with the complex shape, or, when a line is drawn from them to point x, does not intersect any other lines from the remaining (N-1) shapes. It means the algorthm must be performed on the entire set and find the correct locations for all of them, a kind of three body problem.
4. The tooltip must be as close as possible to its associated point
This adds another small caveat which, because of stipulations set in #3 may not be able to be met 'ideally' (what if two shapes are colliding near two close points, which one 'wins out'?).
Again, these are some points to consider as you generate a solution. The result is that you have mathematically 'ideal' locations for your tooltips. However, with these considerations in mind, you may want to look into where realistic concessions may be made. If it's for a design project where the complex shape is unlikely to change then semimanual solutions may be better. If it's for a complex piece of software that will require automatically generated locations you may be able to redesign the UI to give the user the necessary feedback without such a complex solution.
A heuristic:
Compute the centroid of the points.
Place a circle, centered at the centroid, fully enclosing the shape.
Find the places on the circle, where a line form the center through each point
intersects the circle, i.e. project the points on the the circle.
These locations would serve as corners for the tooltip, depending on the which quadrant the point on the circle is, relative to the circle center.
You may increase the circle radius a bit, for aesthetic purposes :)
If I'm not mistaken, this should cover requirements (1), (2) and (3). For (4) you can refine the initial place by moving the tooltip towards the sphere center and checking for intersection with the shape, e.g. using binary search.
Something like this:
There are problems with this approach, of course, but nevertheless it may turn out to be a good starting point for refinement :)
I'm looking for an algorithm that can cut a shape with holes into shapes without holes. Language is preferably C#.
Here's an example image of such a shape.
I'd like to cut that shape into the least amount of smaller shapes without holes getting rid of most of the empty space (white). In this case this might probabyl be a bunch of rectangles. But the original shape might be more complex with rounded holes for example.
For me this sounds like some sort of a bin packing problem and therefore might be solved best with a genetical algorithm.
But in case you know a better approach, it's why I ask.
//edit: alright, I've obviously got some things to explain:
The shape is a Geometry object (WPF) resulting from the subtraction of a bunch of small Geometries from a larger Geometry. So I guess there are vertex points stored somewhere.
The amount of resulting shapes should be minimized, yes, the smallest set.
The resulting shapes should have edges that are as straight as possible with the smallest amount of corners possible.
Unfortunately, I can't provide any code, yet, since I have no clou whatsoever how to practically approach this programmatically. I'm really sorry.
The resulting shapes should be complex but don't have to.
To explain the reason for this: I'm working on a textile crafting (in particular patchworking) program with which one can create patchworks and calculate how much fabric is needed and the cost. Placing the patches on the fabric panel already works somehow using a Tetris like algorithm where patches get placed as close together as possible to reduce waste.
Additionally, everywhere the shape gets cut I need to add a seam allowance to the resulting parts (that's what you can already see in green in the example image).
//edit 2 An acceptable solution might look as follows. Red lines show where shape gets cut in order to get an amount of resulting shapes that don't have holes. The result set contains six large and 25 small rectangles:
However depending on the original shape which might look totally different, even with rounded edges (circular holes), acceptable solutions also might look different. The goal is to get rid of the white areas as far as possible while maintaining some convenience regarding the later actual cutting of the fabric. It'd be somehow counter-productive to have lots of shred that has to be sewed together again (and hence all need seam allowances) only to save a little bit fabric more.
I'm not sure how you want the resulting shapes to be but I'm going to assume that you want them in Polygon. As in an object Polygon which is a vector of 2D vertex points (x,y). What you can do now is use this Clipper library for solving geometric spatial problems. It does polygon subtraction, addition, intersection, and a bit more. Its also fast, free, and no license is needed.
http://sourceforge.net/projects/polyclipping/
Afterwards, you can calculate your seam lengths by just finding the distances along each polygon vertex and adding them up. However, this library does not support curved contours.
My homework is to write a very simple application (Java or C#, I know both), which can detect water level of a glass of water / coke in a picture (it have to draw a line there). I don't even know how to start it. I have googled all day, but have found no useful results. Are there any good algorithms, which can detect the level of the liquid?
The photo is taken from the side, like this:
(it's also good if it detects both lines). So could you help me out with how to start? Use egde detection (are there any good basic algorythms?), or other method?
It would be best would be if it detected water, coke, and every liqued etc....
You are going to have to do some edge detection and then once you have the edges, try and find the level within the glass. You could use a toolkit like Aforge.NET. Then code to detect the edges is pretty simple, for example:
Bitmap b = new Bitmap(Image.FromFile(#"C:\Temp\water.jpg"));
// create filter
Edges filter = new Edges();
// apply the filter
filter.ApplyInPlace(b);
pictureBox1.Image = b;
Yields an image like this:
Now it should be a little bit easier to find the point of water in the glass. Since all of the background noise has been eliminated, you can focus on determining which edge you should key off of.
Check Hough transformation here
It will help you to get the capacity of the glass in question.
Once you know how much water a glass can hold, you can draw two lines onto the image using functions that you write your self. I would advise one line for the glass size and one line for the water level super imposed over the image, you can then use these lines and the maximum capacity of the glass to form a correlation between the two and calculate the level of fluid contained within the glass.
Remember that your professors aren't interested so much in you getting the assignment 100% correct, they are more interested in preparing you to solve problems using your own initiative. Google searching can't always solve your problems.
I have a following problem. A large rectangle contains smaller non-intersecting rectangles (The black rectangles in the picture below) and I need to find an algorithm to fill remaining free area with non-intersecting rectangles(red ones in the picture below). Speed is not an issue for the algorithm. Also if someone would have an example source code of the algorithm I would really appreciate that.
Edit. Small clarification I need to get the coordinates of the red rectangles not to draw them. I am also working with point data not images.
http://koti.mbnet.fi/niempi2/Squares.gif
Like most bin-packing problems this one looks like an NP-hard problem to me. With 2 rectangles, there are 8! (= 40320) possible arrangements you need to consider. Three rectangles produces 12! possibilities, a cool 480 million.
You'll need an heuristic to make this computable. Beyond favoring the outer edges of the rectangles closest to the bounding rectangle, I don't see a good one. You'd need tighter requirements on the resulting rectangles you accept, the number of them isn't going to help. Glad this is not my problem :)
Although there are multiple possible solutions, I think you can get to one fairly easily.
I would work in increasing values along one axis. By scanning all rectangles and ordering their edge's appearances along that axis, you could walk through them and create rectangles as you go. Each time you hit a new pair of corners, you can compare with the rectangles you currently have 'open' and determine what to do (close them, start new, divide, etc).
That statement isn't a complete solution, but I think it gets you from a complex solution to a simple one. It also doesn't seem to be NP complete in terms of performance. You might even be able to get O(n) perf.
An interesting problem. Let us know how you get on.
Look at the Region class.