|
Automatic Text Rotation |
Posted by Steve Valliere on Mar-05-2010 00:06 |
|
I have ongoing issues with trying to reliably detect when axis labels are going to collide with
(and/or overwrite) their neighbors. I often find myself wishing that I could set the font
rotation for the axis labels to "Automatic" (perhaps with a direction option, too?) so that
they could ensure readability.
It would also be nice to have an option to have the renderer automatically remove labels
(instead of rotating them) when they collide/overwrite.
I'm sure both could be sensibly handled by the library.
I'm also fairly sure that the library provides me with the capability to do this myself, but
fewer function calls == better performance, a so built-in implementation should perform
better. |
Re: Automatic Text Rotation |
Posted by Peter Kwan on Mar-05-2010 17:28 |
|
Hi Steve,
ChartDirector will only avoid label overlapping if the labels generated by ChartDirector (eg. in an auto-scaled axis).
If the labels are supplied by your code (eg. using Axis.setLabels), ChartDirector will follow the instructions of your code. If your code tells ChartDirector to display 100 labels, it will display 100 labels.
ChartDirector cannot remove labels provided by your code because it may make the chart not useful. For example, suppose you are plotting a bar chart showing the population of every country in the world, in which the x-axis are labels showing the country names. If we remove some labels, some bars will have no labels, and they become meaningless.
Also, if the first label is very long and overlap with all other labels, should we remove all labels so that there is only one label left? It is not possible to automatically determine which label(s) should be removed in general.
For your case, ChartDirector can be configured to wrap the labels if they are too long (using TextBox.setMaxWidth). This avoids overlapping. This option is useful if there are enough width for the labels (eg. 150 pixels per label), but the label can be really long so the space can be insufficient. On the other hand, if the width per label is very small (eg. 20 pixels per label - enough for 2 to 3 characters), then wrapping will not help. Label rotation will be a better method.
(The width per label is easy to compute. It is the plot area width, divided by the number of labels.)
Hope this can help.
Regards
Peter Kwan |
Re: Automatic Text Rotation |
Posted by Steve Valliere on Mar-05-2010 21:33 |
|
I understand your comments about pathological cases, but I was suggesting an /optional/
feature to allow the library to remove labels when they would overlap. There are many
times when the content of a chart would not be harmed by removing every other label (or
even two out of every three, etc) because the labels have an obvious pattern. In those
instances, the library /could/ be told it is allowed to eliminate labels when necessary.
Of course there are cases when that isn't sensible, but then the option would not be
enabled.
I'd implement this myself in my application, but I've not found any way to enumerate all
of the labels to get their bounding rectangles so that I can check for overlap. It is trivial
to compute the space AVAILABLE for each label, but not to determine how much of that
space IS BEING USED by each label. I suppose that I'd need access to the specific
TextBox for every label in order to do this myself.
And on that point... I've looked at the various ::getLabel() functions and I'm confused
about the parameter being a double (named 'i'). To me, it makes sense to be able to
access the labels by their INDEX (which the 'i' may indicate) which is typically an integer.
The doc says that the parameter is "the specified position" of the label -- but that is very
ambiguous. If my scale goes from 1.23e-5 to 1.27e-5 the position of the first label could
easily be thought of as 1.23e-5, since that's the actual data position. But it could also
be thought of as 1 because it is the first label (or zero, if we're using C-indexing). Could
you explain?
Unfortunately, even with the template TextBox for the labels, and the label strings
themselves, I still cannot find enough information to compute the number of pixels each
label requires. And even if I could, I suspect that I may need to call layoutAxes() to get
everything measured, and then I'd have problems setting new labels with the overlapping
ones replaces with empty strings. This is why I think this would be a great option for the
library.
Also, your entire comment on the subject of my original post (automatic text rotation)
was, "Label rotation will be a better method."
That really doesn't address my question or, in fact, help at all. Is auto-rotation an option
I've not yet found? If so, help! If not, would you consider making it an option in the
future and can you explain how my program can detect when the rotation would be
necessary? I need to support different numbers of elements in re-sizable windows, so I
cannot just hard-code all my sizes like so many of the examples. |
Re: Automatic Text Rotation |
Posted by Peter Kwan on Mar-05-2010 23:08 |
|
Hi Steve,
I think you are correct that we can make this feature (some sort of auto-rotation or auto-label skipping) configurable, so the developer can choose whether to use this feature based on the nature of his data. I will put this in the feature list to be considered in future versions of ChartDirector.
You can measure the space used by a label by using a dummy TextBox. It is like:
TextBox *measurer = c->addText(-9999, -9999, "", "arialbd.ttf", 8);
measurer->setText("abcd");
int width = measurer->getWidth(); //width used by the text "abcd"
measurer->setText("qwerty");
width = measurer->getWidth(); //width used by the text "qwerty"
To get the labels on the x-axis, it depends on where the labels come from. If the labels come from your code, your code already know the labels, so there is no need to ask ChartDirector for the labels.
If the labels are automatically generated by ChartDirector (that is, by auto-scaling), you may use XYChart.layout, Axis.getTicks and Axis.getLabel to find out what are those labels. After layout, you cannot change the font size or rotate the labels, but you can remove some labels by setting them to an empty string using Axis.addLabel.
For the x-coordinate used in the getLabel API, it refers to the x-coordinate of the label. The x-coordinate depends on how the axis is set up.
If the labels on the x-axis is set up using Axis.setLabels or Axis.setLabels2, the labels are treated as names for human reading. The positions of the labels will be considered as 0, 1, 2, 3, ....
If the x-axis is set up using setLinearScale, setLogScale or setDateScale, the x-coordinates will be based on the scale being used. For example, suppose the x-axis is set up as "c->xAxis()->setLinearScale(0, 100, 10);". There will be 11 labels at (0, 10, 20, ... 100). The positions of the labels are (0, 10, 20, ... 100).
"Auto-rotation" is not supported in ChartDirector. If the labels are provided by your code, you may use the "measurer" method above to determine if the labels are too long and need to rotate (or need to skip some labels).
If the labels are automatically generated by ChartDirector, ChartDirector actually will consider the rotation before determining how many labels to generate. So your code should decide whether to rotate the labels first, and ChartDirector will generate more or less labels depending on whether the labels are rotated or not. You may also configure how many labels to generate using Axis.setTickDensity.
Hope this can help.
Regards
Peter Kwan |
Re: Automatic Text Rotation |
Posted by Steve Valliere on Mar-05-2010 23:26 |
|
Thanks for the info on how to measure the labels! It sounds a bit cumbersome and it already takes about 0.17 sec to generate a chart, but it will definitely help.
Also thanks for considering an option for the library to do the label removal. FWIW, it would seem that the same code that does removal could also test for the need to auto-rotate, if that were also an option.... (hint, hint)
Last thoughts about the implementation of these two options (should it occur):
The function to enable automatic label removal could specify that at least N out of every M labels must be kept. The default would be to keep every 1 of 1. If auto-rotation is also allowed, then, if labels would overlap after the keep limit is reached, they get rotated and the overlap operation starts again to see how many to keep/remove using the same rules as it did with the unrotated labels.
I don't know if there's any value to a step size for auto-rotation, but some folks might prefer one direction over another and/or 45 vs 90 degrees. That's for the future to decide.
That would provide maximum flexibility for dynamically sized charts, whether their pixel size and/or number of labels changes.
Again, thanks for listening and even more for considering my ideas and helping me to (attempt to) get them working with the current library! |
Re: Automatic Text Rotation |
Posted by Mark Manning on Jul-17-2010 02:45 |
|
If I might step in here.....
If ChartDirector can detect the TextBox that surrounds a given piece of text (such as labels on a pie chart), then it can detect when those labels are going to collide. If it can do this then why not, instead of removing a label, just stack the labels more efficiently? So instead of:
MyMu#######els
\\
It does:
My Mucked up Labels
I Love it!!! \\
\\ \\
All that would have to be done is to decide which label goes on top of the other one. This can be done by the order in which the labels arrive. So labe #1 ("I Love it!!!") gets to stay where it would normally appear. But label #2 ("My Mucked up Labels") gets shoved up above label #1 and the joiner line is simply extended to the new location (Determined by the bottom-right corner of the TextBox.)
In this way, regular labels would act more like the labels that appear on the side with the joiner lines radiating out to them. |
Re: Automatic Text Rotation |
Posted by Peter Kwan on Jul-17-2010 15:23 |
|
Hi Mark,
Unluckily, so far we still have not found a method that works "robustly" even in some common cases.
The test case we use is as follows:
- Consider a scatter chart with some random scatter points. Some scatter points can be crowded together (as is commonly the case in real charts). Find a way to put text labels for each scatter symbol on the chart, such that:
(a) The text labels will not overlap with each others or with any other symbols. Note that the labels can be rotated and is not necessarily upright.
(b) The join lines will not overlap with the labels or symbols and will not intersect with each others
(c) Everything must stay within the plot area
The above is already a very simple case. We have not considered more complicated and common cases. For example, there may be a line in the chart (it is common to have a line layer together with a scatter layer), and the labels and the join lines are not allowed to intersect with the line layer, etc..
So far, we have only implemented label moving for pie chart label layout, which cannot have the above complications.
In general, we think it is not a good idea to put a lot of randomly positioned text in a chart.
Regards
Peter Kwan |
Re: Automatic Text Rotation |
Posted by Steve Valliere on Jul-20-2010 19:58 |
|
Peter,
I hope you're [still?] considering an option (or options) to allow applications using ChartDirector to tell ChartDirector when and how many labels may be removed if they collide, and when and how much to rotate labels when they collide. It seems like it would be vastly more efficient for ChartDirector to perform these functions, even at a simple level than for applications to attempt it themselves.
I can speak from my experience implementing your suggestion from earlier in this thread that I could never quite get it to work reliably. Apparently, there are some over things that work their way into the rendering that cause my code to sometimes have gaps large enough for the labels I suppressed, or sometimes the labels touch (just barely). I never found a balance point between those two, so I had to settle for sometimes dropping labels that would've fit. Given how well ChartDirector does with everything else, I truly believe that you could do a better job of those functions internally, if you we told how many labels could be dropped before they're allowed to collide. |
Re: Automatic Text Rotation |
Posted by Mark Manning on Jul-21-2010 00:20 |
|
Actually, having spent almost 20 years at NASA working with 3D everything - I have to disagree. We were met with this problem many times and did not have any kind of a problem with handling this. Here is my suggestion (if my fingers will type correctly - I seem to be having a bit of a problem typing right now :-/ ).
We would create what we called a bounding box around an object. This was the three dimensional area the object took up. You can do the same thing with 2D objects as well. As I wrote, all you have to do is to create the top-left, bottom-right pairs if you want a rough idea of what the object looks like. This allows the next object to test whether it falls within or without the older object. Once the test is through, you add the new object to the list of objects to test against. TRUE - this does create an N! problem but when you are dealing with only hundreds of test - it isn't all that bad. Try doing this with over thirty million data points and having to go through them in less than a second so the next frame of an animation can display. That's when you have to start doing what is called culling of the data.
In the 2D world, the thing to do is to create a blank, white square equal to the size of the plotting area. Create a shadow image of what you are going to put onto the plot (like a text box, rotated, inverted, embossed, or whatever - it still will create a shadow image). Using the shadow image (which will become a black & white image) you test the black pixels in the shadow image against the larger white plotting area. If, when you do the test, you hit a black pixel already on the larger plotting area image - then you have collided with something already there and you have to adjust your current image. You do this by having (again) kept track of the bounding boxes for the other objects that came before this. (So the first object has the whole plotting area to put itself into. The second object can not fall in the first object's space, and so forth.) There are many free and open source locations on the internet that show you how to do this so you don't have to re-invent the wheel. One really good website is Paul Bourque's math website where he even gives you the source code (sometimes) on how to test for various things.
Believe me - when dealing with something like the international space station with all of those solar panels and hundreds of little tester boxes of all shapes and sizes - you have to know whether or not something has collided with something else. It used to be that it took hours to figure these things out. But because of people like myself and others who have worked on these problems for years - you should be able to take advantage of our work and papers as well as the thousands of people who have worked on game theory papers to implement a simple - yet robust - collision detection routine which would take care of this problem for you.
And as for why I haven't written my own charting program for where I work and not bought ChartDirector? I was. I had built a windowing system, frame system, chart system, and was working on the legend system when my company decided I was working too long on the project (only two weeks mind you) and they bought ChartDirector. After seeing what else your company had already done with charts I had to agree. It would have taken me months to get to where you are already. But I'd already written something to take care of colliding titles. If I can do that in two weeks - you should be able to do so as well.
Please - fix this. Thanks. |
Re: Automatic Text Rotation |
Posted by Mark Manning on Jul-21-2010 00:38 |
|
I thought I might add some more here:
Collision detection is fairly simple to implement. Here is an easy method:
Plot Area: Black (0x000000)
Old Objects: Blue (0x0000ff)
New Objects: Red (0xff0000)
A new object is put onto the black background (so some area on the Plot Area will become red). In other words - just XOR it onto the Plot Area. Then scan the Plot Area for magenta (0xff00ff). If you find it - you collided. If you didn't then redraw the new object in Blue onto the Plot Area. Add the bounding box for the new object to the list. Repeat. This requires two draws and one scan of the Plot Area at a minimum.
If magenta is found, XOR the new object back off of the Plot Area. Depending upon where the magenta was found, correlate the location of the pixels with the bounding box. This tells you where you collided and you move in the opposite direction from there to place the new object. You determine how far to move the object by the bounding box of the object you hit. (So if you hit close to the bottom-right pair on the shadow image you move in the top-left pair directiion and so forth.) Of course there are caveats like "What if I'm going off the top of the plot?" Use common sense and act accordingly.
When you are through you will wind up with a black and blue shadow image of what you have done and everything should be arranged properly. No matter what orientation they are at, what they look like, or what special effect you give to the new object - it should still create a shadow image. Usually, you can create a shadow image by simply changing any/all colors to the color of your new object (in this case red).
If you want to ALWAYS have an extra pixel or two around a given object, then what you do is to increase the size of the object's shadow image by twice as much (ie: if you always want one pixel around all sides of a shadow image then you need TWO pixels (1 left + 1 right and 1 top + 1 bottom) added on to the shadow image's size and you have to do a one pass scan to add the extra pixel on to the image itself.)
You can use white instead of black. In that case you are looking for the opposite colors (ie: Cyan and green). The XOR is what makes it all possible.
Later! |
Re: Automatic Text Rotation |
Posted by Peter Kwan on Jul-21-2010 04:00 |
|
Hi,
It is correct that detection collision is easy, especially for rectangular objects.
The hard part is in moving the text. We cannot just arbitrarily move the text, because the text can hit something else (either other text, or a scatter symbol, or a line segments of a line chart, etc) if it is moved.
For data point labelling, the text must stay nearest to the data point that it labels. If it is moved to stay closer to another data point, it may be mistaken as the label for that point. A join line can be used to join the text to the data point to avoid confusion, but then we have to handle the problem that the join lines can intersect with some other text or chart objects (scatter points, line segments of a line chart), or will intersect with themselves, ...
Currently, ChartDirector can only automatically move labels for pie charts, and for axis labels created by ChartDirector itself.
Finally, we must note that the above is (avoid lable collision) logically impossible in general, because we cannot put arbitrarily large number of labels in a finite space without collision (it would be possible in a web page or in "space" in which the region can grow indefinitely). So all algorithms work only up to a certain extent.
For scatter chart labelling, a simple algorithm I suggest is:
For each scatter point, try to add a label to the "top-center" position. Check if the label collide with any scatter points or previous labels or is outside the plot area. (Checking overlapping of bounding boxes should be very easy.) If it collides with something, try other alternative positions ("bottom-center", "top-left", ....) until a suitable position is found. If the label collides with something in all positions, you may rotate the label by 90 degrees and try again (if you can allow label rotation). If all fails, then discard the label.
The above should work for scatter charts, but not for line charts with data symbols, because it does not check for collisions with line segments.
Regards
Peter Kwan |
Re: Automatic Text Rotation |
Posted by Mark Manning on Jul-22-2010 02:12 |
|
Peter,
Ok - first I'm talking about pie charts and not scatter charts. Our labels are overlapping each other on the 3D pie charts.
Second - remember I said you start off with a blank background? Also, I said you keep a list of what is being drawn onto that background? This also includes anything else besides the titles.
On those things that you have no choice on drawing them (like the lines, dots, figures, main titles, grids, and anything else you just have to draw) - you can put the blue color shadow color on to the blank background panel. Then, when you go to put the titles on, those areas are off limits. (Although I would think grids are fair game for being overlapped by titles and thus would not be drawn on the blank background.)
As for "arbitrarily being drawn" - that is why you have a connecting line like on pie charts. So you can draw a simple line to where the title has moved. Using common sense, you can not have all of the titles placed one on top of the other. Therefore, like in pie charts, you should use a line to go from the data point to the title. Whereever that is located. And like how they are done on the piecharts (when the titles are off to one side) - you should be able to have the lines combine and then extract themselves as needed.
On the pie chart thing - my boss wants the pie charts NOT to have the lines out to the sides with the titles stacked. He wants the titles next to the pie chart but not overlapped. After reading through the documentation - there doesn't appear to be a way to do that. Like the scattergrams, the pie charts should be able to figure out where the titles should go as they move around the pie chart. Like the scattergram problem, you have to keep track of where each TextBox would appear and adjust it accordingly. |
Re: Automatic Text Rotation |
Posted by Mark Manning on Jul-27-2010 04:38 |
|
Ok! Here is a work-around for those people who are being frustrated by pie charts with labels that lay one on top of the other. As Peter said before - you can use SideLayouts. However! Let's say you want those labels to go around the pie chart and now lay off to one side and you do not want the colorful backgrounds. Here is how I did it.
1. You want to make your pie chart in the normal way.
2. You want to maintain a total for the entire pie chart. Just as if you were not using ChartDirector to do this for you.
2a. NOTE: It would be nice if the percentages generated by ChartDirector via the Sector information as then you don't have to do the calculations yourself.
3. Because the labels that stack are usually because there are small slices in the pie chart which are too small to hold a single label, we want to look for those and adjust the distance away from the chart they are going to sit. To do this, we have to use the SECTOR section of ChartDirector's documentation. Look up the Sector.setLabelLayout information about this. The description and usage is:
Description
Sets the layout method and location of the sector label.
Usage
setLabelLayout(layoutMethod [, pos ])
4. Begin a loop where you are going to go through each and every slice of the pie chart so you can get the sector information from the pie chart.
$c = -1;
foreach( $count_1 as $k=>$v ){
$c++;
$distance = 30 - ((($v/$total*100) < 10) ? 30 : 0);
$sector = $pie->getSector( $c );
$sector->setLabelLayout( SideLayout, $distance );
}
Calculate the distance a label should be based upon the percentage the slice uses up of the pie. Larger slices the label can be farther away. Smaller slices have to be closer. This forces the program to put the labels near to where the slice actually resides and gives you small join lines to each of these labels. Note that we use the "SideLayout" which forces ChartDirector to correctly stack the labels one on top of each other. Check out the uploaded image.
NOTES: There is something weird going on with the SideLayout. Note that both the left and right side labels (ie:"Paid" and "Accepted") are of different lengths even though they both are set to a distance of 30 pixels. I believe this is the old positive/negative problem I've run in to before when dealing with positive versus negative directional movement. The nice thing though is that the "Error" and "Processing" labels are now a lot closer to where they should be and they are not one on top of the other.
In any event - here is one possible answer to making labels work in ChartDirector.
|
Re: Automatic Text Rotation |
Posted by Mark Manning on Jul-27-2010 07:07 |
|
Here are some corrections to my diction which, after re-reading it isn't all that great sometimes. :-P
Mark Manning wrote:
those labels to go around the pie chart and now lay off to one side
That should be "...and not lay off...".
3. Because the labels that stack are usually because there are small slices in the pie...
That should be "Because the labels that stack are usually small slices in the pie..."
4. Begin a loop where you are going to go through each and every slice of the pie chart so you can get the sector information from the pie chart.
That should be "...so you can get the sector information about each slice."
Calculate the distance a label should be based upon the percentage...
That should be "Calculating the distance to a label..."
Larger slices the label can be farther away.
That should be "Larger slices should be placed farther away from the pie chart."
Smaller slices have to be closer.
That should be "Smaller slices should be closer to the pie chart."
Sorry - just can't stand my own bad grammar or diction.
Notes: Why should labels on larger slices be farther away from the pie chart than labels for smaller slices of the pie? Optical illusion (or delusion as my old boss used to say). The large slice makes the label look smaller, by pushing it out away from the pie chart a bit more the label looks larger. Labels look larger and make the small slices stand out more if the text is closer to the slice (but not if the text overlaps the slice - then the slice simply looks wiped out). |
Re: Automatic Text Rotation |
Posted by Peter Kwan on Jul-28-2010 01:33 |
|
Hi Mark,
Thanks a lot for your code. I am sure this will be of great help to other people with similar requirements.
Regards
Peter Kwan |
Re: Automatic Text Rotation |
Posted by Mark Manning on Jul-28-2010 23:13 |
|
I have figured out what is wrong with the pie chart's join lines on the right hand side. I exploded the chart and that movement of the slice is what clobbered the join line. So the equation of where the join line should start (next to the pie chart) needs to be modified so it takes into account exploded slices.
Also, suggestion, Allow the user to have control over whether or not the join line has the radius of the circle added on to the side layout's length of join line. If a simple true/false flag was allowed on the call to make labels become SideLayout labels were applied (and defaulted to TRUE), then the side labels would then be able to lay next to the pie chart itself (instead of off to the side like they are now). |
Re: Automatic Text Rotation |
Posted by Peter Kwan on Jul-29-2010 03:39 |
|
Hi Mark,
Thanks for update.
I remember the side layout is designed such that exploding a sector will not change the position of the label. This is necessarily, otherwise if one explodes some sectors but not other sectors, the labels will not align. Also, keeping the label position constant can make it easier to predict the required pie width.
For the pie chart label layout, thanks a lot of your suggestion. We will consider your idea seriously in future versions of ChartDirector.
I must admit we are always worried about "general case". I have attached an example, which is not uncommon. In the attached example, the top 3 labels on the left block access of the "pink" label, so that there is no way the pink label can join with the pink sector without crossing the pie. The solution is to pull the labels further from the chart (which is what the side label layout is doing).
I have also added a "green" sector, which shows that the label distance from the pie should not depend on the data value in some cases. (In the "general case", the data are not necessarily sorted. The large/small values can interleave.)
In real applications, the data are usually dynamic and unpredictable, so it is hard to know if the case in the attached example will occur. From our prespective, a new layout method would need to be robust enough to survive these common cases.
Regards
Peter Kwan
|
Re: Automatic Text Rotation |
Posted by Steve Valliere on Jul-29-2010 04:23 |
|
Peter Kwan wrote:
I must admit we are always worried about "general case".
That's great but... Sometimes your user may not need such power, and a simple algorithm could be used instead (based on a user option). After all, why should all of the users with less complex needs be forced to implement the complex solution of measuring all of the labels, determining their positions, checking for overlap, etc. just because a few users have somewhat pathological cases?
In your pie example, it seems to me that all of the problems I think you described would be solved if the labels were allowed to appear all around the chart, instead of unnaturally forcing them to the sides (if having them to the sides was your point, I missed it, sorry, I don't do pie charts normally).
For another example, a user that is creating a bar or XY graph with 100-200 points along the X axis (NOT a scatter plot, mind you), then it would often be easy to use only one label in 10 or 20 and a simple algorithm for removing them would work great. Yes, the user could provide a set of labels with the unnecessary labels set to empty strings, but determining which are going to overlap is much easier for the chart library than the user. Also, in cases like these, it would be easy for the chart library to determine that label rotation is necessary to prevent overlap as well (that /was/ the original point of this thread, after all).
If a users doesn't like what he/she gets with the simple label removal/rotation options, then they can try to implement it themselves as must always be done now. But for all of the users with less complex needs, such a feature would be a boon. |
Re: Automatic Text Rotation |
Posted by Mark Manning on Jul-29-2010 07:26 |
|
To Peter:
I see that you did not remove the colorful boxes around the text. If you did that the text box would not collide with the pie chart. In our case, we had a maximum of five entries to the pie chart. If I was expecting more (like twenty or thirty entries) I would have moved the labels further away. And, another suggestion for Chart Director, I would hope that Chart Director would stagger the label if there were too many of them to display on a single line. Again, this would require Chart Director to keep a list of where the Text Boxes were being placed. Since Chart Director already knows the maximum height of the chart, where the title is being placed, the width of the chart, and the size/location of the pie chart itself (explosions and all) - it should be fairly simple to calculate how tall twenty labels would be if most of them fell on one side or the other. It could then see about staggering the labels to see if it could fit them all onto the one side. (The same holds true if it splits the labels because at some point you have to go beyond just stacking them.)
To Steve:
If you had, say, 50,000 points you have to put on a line chart, I agree that there should be some way to say "I only want one label every X number of points" or "I only want labels at the highest/lowest points" or some other methodology to reduce the number of labels. I recall one product which you gave a list of where you wanted the labels to appear (ie: 5, 1000, 2500, etc...) and the labels only appeared at those locations. Any of these would be preferable to having 50,000 labels all piled one on top of the other.
All:
In any event, our needs have been met by the technique I used. We needed labels that did not collide and now they do not. We only needed a maximum of five labels which are highly unlikely to collide even if four of them are all tiny slices in one location. If each join line was allowed to be a different length and if the labels always were drawn at the end of the join line (whether the join line is displayed or not), then the user could adjust each label on an as needed basis. The real problem here though, may just be not enough control by the user or just not enough knowledge about how ChartDirector works. In other words: Not being able to get the information needed in order to make a decision on what to do and then not having the proper tools to be able to effect those changes combine to cause trouble. This isn't to say that there might not be a way to do something - Obviously there are lots of functions that you can call to achieve what you need to do. So it might just be ignorance of how to do something that is causing the problem. But I can not find such routines as "Where does the join line start from?" or maybe I should say "Where is the middle of the pie slice on the outer arc?". Knowing where that point is would eliminate the problem of the join line not appearing/starting in the correct location - but it also would make it so you could gather all of these things up and adjust the lengths of the join lines accordingly based upon how far apart they were versus where they are on the pie chart itself.
So. Steve's problem to one side (for me), our problems have been solved.
When I was working on developing a charting package for where I work (before the management decided my time was better spent doing other things and we would buy a pre-made charting piece of software), I had already gone through six or seven attempts at starting to work on a charting program. I had finally settled on creating my own windowing system in PHP. By creating an underlying windowing system I could then encapsulate each part of the chart into its own area. This led to my having the following: Window->Frames and Frame->Charts. Followed by Chart->(xAxis, yAxis, Legend,...). Each of these gathered their own windowing setup. (So WINDOW had the windowing setup but FRAME, CHART, XAXIS, YAXIS, LEGEND, TITLE, etc.. all had it too.) Although this took me quite a while to create, once the basic class was set up, all of the other things began to fall into place quickly. The nice thing about this approach was that as each item was added to the windowing system above it, that system automatically adjusted itself to accommodate the new item. Further, if the items could not all fit, they automatically adjusted their sizes so they could fit. The reason they could do this was because they all maintained their original sizes and simply did a 1:1 ratio on the change to come up with a percent difference in size. When the user went to actually build the chart, these percent differences were applied, the new box size was calculated, checked against what was wanted, and adjusted again until everything fit. Thus, something like a 12pt font might actually become a 6pt font if need be. I thought I was on to something but since all work was stopped on that it is just sitting there. Maybe later I'll get to work on it again. I will state though that my program was in the rudimentary stages of development and could only create a pie chart. Not explode it, 3D it, or anything like that. So I still had quite a ways to go. Which is why we opt'ed in for ChartDirector. |
|