Home All Groups Group Topic Archive Search About
Author
19 Feb 2009 10:27 PM
David
I have my own graph routine which labels time on the X Axis.
The problem I'm having is labeling different compression periods based on
the time of the compression period.

The amount of space between X points is variable, so I need to somehow
adjust the labeling  (more or less labels) based on the  space available
while keeping the correct time associated with the X point when the label is
placed.

Anyone have a suggestion?

Thanks
David:

Author
19 Feb 2009 10:49 PM
Larry Serflaten
"David" <dw85745***@earthlink.net> wrote
> I have my own graph routine which labels time on the X Axis.
> The problem I'm having is labeling different compression periods based on
> the time of the compression period.
>
> The amount of space between X points is variable, so I need to somehow
> adjust the labeling  (more or less labels) based on the  space available
> while keeping the correct time associated with the X point when the label is
> placed.
>
> Anyone have a suggestion?


That amounts to a bit of math, but without context, it would be difficult
to explain.  If you post example code of what you've tried, that would
add context to the problem so that others might fill in the missing details.

LFS
Author
19 Feb 2009 11:51 PM
Ivar
"David" <dw85745***@earthlink.net> wrote in message
news:uyr02EukJHA.1248@TK2MSFTNGP03.phx.gbl...
>I have my own graph routine which labels time on the X Axis.
> The problem I'm having is labeling different compression periods based on
> the time of the compression period.
>
> The amount of space between X points is variable, so I need to somehow
> adjust the labeling  (more or less labels) based on the  space available
> while keeping the correct time associated with the X point when the label
> is placed.
>
> Anyone have a suggestion?

So you have an X axis that that represents time, it's assumed you know how
much time to represent, maybe a few seconds or a thousand days from left to
right, and you would know how wide (in scale units ) the disply area is and
where the leftmost point (StartTime) is,  It's best (but not compulsory to
work in Pixels). You would need to calc a ScalueUnitToTime varible of how
much time per scale unit.
ScaleUnits divided by total display time
Then the X point of where to put your 'Lable' is
So: Label1.Left = TimeZeroX + AmountOfTime * ScaleUnitToTime

If the total display time is 3 minutes and is 600 Pixels wide then
ScaleUnitToTime would be 600 / 180, so each second is 3.33 pixels.
So 47 seconds would be 47 * 3.33 = 156 pixels from the zero position.

Clear as mud?

Ivar
Author
20 Feb 2009 12:39 AM
James Hahn
Take a look at the MeasureString graphics method.
http://msdn.microsoft.com/en-us/library/6xe5hazb.aspx

This will give the size of each label.  You might work with the sizes of
specific labels, or you might work with a 'typical' label size.

Once you have the size, start from the left edge of the graph and place the
first label (or the first one where the text can be positioned to match the
point you are labelling) and note where the label ends. Continue to the
right, only labelling those points where the the label position (starting
point) is a certain distance beyond the end of the previous label.

In other words, for each point find the width of its label. and subtract
half that from the point to find the label start (assuming you want the
label centred under the point).  The first label is the first point which
has a label start of 0 or greater. The next point is the first point that
has a label start of the end of the previous label plus an allowance for
spacing.

For instance
Pt    W     0.5  Start      End  Spc Next
10    50    25    -15
20    50    25    -5
40    45    22    18    *    62    3    65
50    40    20    30
65    50    25    40
80    40    20    60
110  35    17    93    *    127 3    130
120  40    20    100
150  40    20    130 *    170  3    173
etc

Show quoteHide quote
"David" <dw85745***@earthlink.net> wrote in message
news:uyr02EukJHA.1248@TK2MSFTNGP03.phx.gbl...
>I have my own graph routine which labels time on the X Axis.
> The problem I'm having is labeling different compression periods based on
> the time of the compression period.
>
> The amount of space between X points is variable, so I need to somehow
> adjust the labeling  (more or less labels) based on the  space available
> while keeping the correct time associated with the X point when the label
> is placed.
>
> Anyone have a suggestion?
>
> Thanks
> David:
>
>
Author
20 Feb 2009 9:26 AM
Mike Williams
"James Hahn" <jh***@yahoo.com> wrote in message
news:O2pMMPvkJHA.4132@TK2MSFTNGP04.phx.gbl...

> Take a look at the MeasureString graphics method.
> http://msdn.microsoft.com/en-us/library/6xe5hazb.aspx

That's dotnet stuff and judging by the fact that the OP posted to the
Classic VB newsgroup he is almost certainly using Classic VB (VB6 or
earlier), in which case the dotnet solution you posted will be of no use to
him. In VB6 he can use the TextWidth function on a DC set to the same font,
or he can use or he can simply read the Label's width (if it has Autosize
set to True).

Mike
Author
20 Feb 2009 1:57 PM
David
Thanks for responses guys.
I'm currently using TextWidth and doing what Mr. Hahn has posted.

My labels show up, but as compression time increases the X label value tends
to get cut off when the next label is placed.
I need to somehow set up a variable which is a function of compression so
labels are increase along with compression.

For example.   Say you are posting minute data so that each point represents
one minute.  The time value would be a textwidth of 5
(hh:mm). and would need to  be space every so often to look good.

Now lets say every point repsented every 153 minutes.  You would still have
a textwidth of 5 (hh:mm) but the label spacing would need to increase
accordingly.

So without some form of select/case with every possible minute,
some variable relationship needs to be established between the compression
and label spacing.

Thanks
David


Show quoteHide quote
"James Hahn" <jh***@yahoo.com> wrote in message
news:O2pMMPvkJHA.4132@TK2MSFTNGP04.phx.gbl...
> Take a look at the MeasureString graphics method.
> http://msdn.microsoft.com/en-us/library/6xe5hazb.aspx
>
> This will give the size of each label.  You might work with the sizes of
> specific labels, or you might work with a 'typical' label size.
>
> Once you have the size, start from the left edge of the graph and place
> the first label (or the first one where the text can be positioned to
> match the point you are labelling) and note where the label ends. Continue
> to the right, only labelling those points where the the label position
> (starting point) is a certain distance beyond the end of the previous
> label.
>
> In other words, for each point find the width of its label. and subtract
> half that from the point to find the label start (assuming you want the
> label centred under the point).  The first label is the first point which
> has a label start of 0 or greater. The next point is the first point that
> has a label start of the end of the previous label plus an allowance for
> spacing.
>
> For instance
> Pt    W     0.5  Start      End  Spc Next
> 10    50    25    -15
> 20    50    25    -5
> 40    45    22    18    *    62    3    65
> 50    40    20    30
> 65    50    25    40
> 80    40    20    60
> 110  35    17    93    *    127 3    130
> 120  40    20    100
> 150  40    20    130 *    170  3    173
> etc
>
> "David" <dw85745***@earthlink.net> wrote in message
> news:uyr02EukJHA.1248@TK2MSFTNGP03.phx.gbl...
>>I have my own graph routine which labels time on the X Axis.
>> The problem I'm having is labeling different compression periods based on
>> the time of the compression period.
>>
>> The amount of space between X points is variable, so I need to somehow
>> adjust the labeling  (more or less labels) based on the  space available
>> while keeping the correct time associated with the X point when the label
>> is placed.
>>
>> Anyone have a suggestion?
>>
>> Thanks
>> David:
>>
>>
>
Author
21 Feb 2009 8:02 AM
James Hahn
If the procedure I suggested is not working then your problem is not clear
to me.

"David" <dw85745***@earthlink.net> wrote in message
news:OZmp3M2kJHA.5732@TK2MSFTNGP05.phx.gbl...
> Thanks for responses guys.
> I'm currently using TextWidth and doing what Mr. Hahn has posted.
>
> My labels show up, but as compression time increases the X label value
> tends to get cut off when the next label is placed.
> I need to somehow set up a variable which is a function of compression so
> labels are increase along with compression.
>
> For example.   Say you are posting minute data so that each point
> represents one minute.  The time value would be a textwidth of 5
> (hh:mm). and would need to  be space every so often to look good.

I assume this case is OK because each minute is positioned more than 5
characters apart, so the labels do not overlap.

> Now lets say every point repsented every 153 minutes.  You would still
> have a textwidth of 5 (hh:mm) but the label spacing would need to increase
> accordingly.

Now (I assume), each minute point is very close together and to print a
label for each one would make them unreadable. Therefore you want to print
labels for only some of the minute points, but you need to work out which
ones.

If my assumption is correct then the process I described will do what you
want - it will print labels only for those points where the position of the
first character of the label is beyond the end of the last character of the
previous printed label.

You would use a loop that calculates the numbers I listed in the table for
each minute, but print the label only when the start position for the label
is greater than the end of the previous one - the labels I have marked with
an asterisk in the example.

> So without some form of select/case with every possible minute,
> some variable relationship needs to be established between the compression
> and label spacing.
>
> Thanks
> David

There is an alternative procedure which calculates the number of labels that
can fit on the X axis (assuming they are all the same size) and then divides
that number into the range of values to determine the value increment at
which each label is placed.

For instance-
Width = 100, Label width = 5 + 2 spaces --> room for 14 labels
X-Scale = 0 to 8000 minutes --> print a label every 570 minutes
Author
22 Feb 2009 6:08 PM
David
Mr Hahn:

Thanks for response.  I am using VB6 not Net but the logic should be the
same whether you are using TextWidth or MeasureString.

The key area I'm trying to address is the "Number of Labels" placed
across the screen.  In your original post you aptly point out:

A.  Continue to the right, only labelling those points where the the label
position (starting point) is a certain distance beyond the end of the
previous label.

and

The first label is the first point which has a label start of 0 or greater.
The next point is the first point that has a label start of the end of the
previous label plus an allowance for spacing.

I do the above as noted.

-------------------
Where the issue lies is this.

As I spin through my display loop I put down my datapoint, then I check to
see if that point is the beginning of a day, if so I place "mm/dd" at that
location, determine the width of those characters (5) and calculate where
the next label can be placed.  I then lay down datapoints until I'm => that
spacing, then place another label for the next point "hh:mm".  I then
calculate that that label width(5), determine where the next label point can
be placed and continue to loop.
This places a lot of labels.  If display time period changes  to days for
example, I mark every month and then label every seventh day.

I could have a variable which adjusts the number of dependent labels
"hh:mm" or "day", but I'm looking for some way to adjust this automatically

Any ideas?



Show quoteHide quote
"James Hahn" <jh***@yahoo.com> wrote in message
news:epP9Ar$kJHA.3380@TK2MSFTNGP04.phx.gbl...
> If the procedure I suggested is not working then your problem is not clear
> to me.
>
> "David" <dw85745***@earthlink.net> wrote in message
> news:OZmp3M2kJHA.5732@TK2MSFTNGP05.phx.gbl...
>> Thanks for responses guys.
>> I'm currently using TextWidth and doing what Mr. Hahn has posted.
>>
>> My labels show up, but as compression time increases the X label value
>> tends to get cut off when the next label is placed.
>> I need to somehow set up a variable which is a function of compression so
>> labels are increase along with compression.
>>
>> For example.   Say you are posting minute data so that each point
>> represents one minute.  The time value would be a textwidth of 5
>> (hh:mm). and would need to  be space every so often to look good.
>
> I assume this case is OK because each minute is positioned more than 5
> characters apart, so the labels do not overlap.
>
>> Now lets say every point repsented every 153 minutes.  You would still
>> have a textwidth of 5 (hh:mm) but the label spacing would need to
>> increase accordingly.
>
> Now (I assume), each minute point is very close together and to print a
> label for each one would make them unreadable. Therefore you want to print
> labels for only some of the minute points, but you need to work out which
> ones.
>
> If my assumption is correct then the process I described will do what you
> want - it will print labels only for those points where the position of
> the first character of the label is beyond the end of the last character
> of the previous printed label.
>
> You would use a loop that calculates the numbers I listed in the table for
> each minute, but print the label only when the start position for the
> label is greater than the end of the previous one - the labels I have
> marked with an asterisk in the example.
>
>> So without some form of select/case with every possible minute,
>> some variable relationship needs to be established between the
>> compression and label spacing.
>>
>> Thanks
>> David
>
> There is an alternative procedure which calculates the number of labels
> that can fit on the X axis (assuming they are all the same size) and then
> divides that number into the range of values to determine the value
> increment at which each label is placed.
>
> For instance-
> Width = 100, Label width = 5 + 2 spaces --> room for 14 labels
> X-Scale = 0 to 8000 minutes --> print a label every 570 minutes
>
Author
23 Feb 2009 12:19 AM
Larry Serflaten
Show quote Hide quote
"David" <dw85745***@earthlink.net> wrote

> The key area I'm trying to address is the "Number of Labels" placed
> across the screen.  In your original post you aptly point out:

> -------------------
> Where the issue lies is this.
>
> As I spin through my display loop I put down my datapoint, then I check to
> see if that point is the beginning of a day, if so I place "mm/dd" at that
> location, determine the width of those characters (5) and calculate where
> the next label can be placed.  I then lay down datapoints until I'm => that
> spacing, then place another label for the next point "hh:mm".  I then
> calculate that that label width(5), determine where the next label point can
> be placed and continue to loop.
> This places a lot of labels.  If display time period changes  to days for
> example, I mark every month and then label every seventh day.
>
> I could have a variable which adjusts the number of dependent labels
> "hh:mm" or "day", but I'm looking for some way to adjust this automatically
>
> Any ideas?


To advance that same idea a little further, you might add an array (or two)
that denotes the lable format associated with a convenient unit measurement.

If, for example the scale is in seconds, your format might be "nn:ss" with
the convenient measurement at 30 seconds.  If the scale is minutes, the format
might be "hh:nn" with the unit measurement again at 30.  Hours might be
"hh:nn" with units at 1 or 12 (depending on size of display).  For scales up
past days and months added tests would be needed to align to Sundays
and to the beginning of the month.

But the idea is that in addition to your test for the next possible location,
you could include a test for the convenient measurement (a Mod operation)
such that seconds and/or minutes labels appear at 0 and 30, and hours
would have labels (depending on display size)  each hour or at midnight and
noon.

Any way you go at it, it sounds like a healthy chunk of decision making
code....  <g>

LFS
Author
23 Feb 2009 1:14 AM
James Hahn
I think your original comment might be correct - you will need a different
function for each case:

The cases are something like:
hh:mm  mm:ss  mm:ss  mm:ss...
dd:hh   hh:mm  hh:mm  hh:mm...
mm/dd   dd:hh  dd:hh  dd:hh...
yy/mm  mm/dd  mm/dd  mm/dd...

Not quite as you described it, but if you wanted a single function to do the
job then the description would have to be something like that. While
adjusting the labels for the different cases would be relatively easy, the
test for start of hour/day/month, and the calculation of the value for each
label would be different enough to suggest that the simplest solution is to
get a routine that works at one scale then duplicate it at the others, with
changes for both the labels and the calculations.  This assumes that each
display can be categorized into one of the above formats.

If you need to (for instance) mark the start of a new day when you are
displaying hours and minutes, so that it could be something like:
23:30  23:50  02/23  00:10  00:30  00:50  01:10
then the approaches I suggested won't work.  The only way I could think of
to do that would require a routine that processed the whole range for month
markers, then each month (sub)range for day markers then each day (sub)range
for hour markers and each hour (sub)range for minute markers and finally
each minute (sub)range for seconds markers. This is a typical recursive
routine. At any level there may be only one sub-range  - ie, the span is
less than one unit of the current range.  Or, there could be several
sub-ranges, each one of which is then processed recursively to see if it
needs intermediate markers.  Recursion would stop as soon as there was no
room for a marker, or when it got to the seconds level.  The original
algorithm would work for placing the markers, as each subrange would appear
to be a complete graph. Doing it from the top down (months, then days then
hours etc) can also take care of the problem that (for example) an
hour:minute marker of 00:00 should actually be promoted to a mm/dd marker,
as this marker will have already been inserted at the higher recursion
level.  But this is becoming very complex code.  Because it considers the
whole range it could not be done as points are placed, but only after the
extent of the graph was known. I don't think you could do this if it was a
moving graph without having the labels jump around unexpectedly.

Show quoteHide quote
"David" <dw85745***@earthlink.net> wrote in message
news:uEdINiRlJHA.1288@TK2MSFTNGP02.phx.gbl...
> Mr Hahn:
>
> Thanks for response.  I am using VB6 not Net but the logic should be the
> same whether you are using TextWidth or MeasureString.
>
> The key area I'm trying to address is the "Number of Labels" placed
> across the screen.  In your original post you aptly point out:
>
> A.  Continue to the right, only labelling those points where the the label
> position (starting point) is a certain distance beyond the end of the
> previous label.
>
> and
>
> The first label is the first point which has a label start of 0 or
> greater. The next point is the first point that has a label start of the
> end of the previous label plus an allowance for spacing.
>
> I do the above as noted.
>
> -------------------
> Where the issue lies is this.
>
> As I spin through my display loop I put down my datapoint, then I check to
> see if that point is the beginning of a day, if so I place "mm/dd" at that
> location, determine the width of those characters (5) and calculate where
> the next label can be placed.  I then lay down datapoints until I'm =>
> that spacing, then place another label for the next point "hh:mm".  I then
> calculate that that label width(5), determine where the next label point
> can be placed and continue to loop.
> This places a lot of labels.  If display time period changes  to days for
> example, I mark every month and then label every seventh day.
>
> I could have a variable which adjusts the number of dependent labels
> "hh:mm" or "day", but I'm looking for some way to adjust this
> automatically
>
> Any ideas?
>
Author
23 Feb 2009 12:59 PM
David
Thanks Mr. Hahn and Mr. Serflaten for your time and input.

Mr Serflaten I liked your idea of picking a "specific" subperiod time on
which to place the label.  This would force the sublabels to occur less
frequently.  Will give it a go.

Please consider this thread closed unless anyone has other suggestions.

David



Show quoteHide quote
"James Hahn" <jh***@yahoo.com> wrote in message
news:evQzzQVlJHA.2384@TK2MSFTNGP04.phx.gbl...
>I think your original comment might be correct - you will need a different
>function for each case:
>
> The cases are something like:
> hh:mm  mm:ss  mm:ss  mm:ss...
> dd:hh   hh:mm  hh:mm  hh:mm...
> mm/dd   dd:hh  dd:hh  dd:hh...
> yy/mm  mm/dd  mm/dd  mm/dd...
>
> Not quite as you described it, but if you wanted a single function to do
> the job then the description would have to be something like that. While
> adjusting the labels for the different cases would be relatively easy, the
> test for start of hour/day/month, and the calculation of the value for
> each label would be different enough to suggest that the simplest solution
> is to get a routine that works at one scale then duplicate it at the
> others, with changes for both the labels and the calculations.  This
> assumes that each display can be categorized into one of the above
> formats.
>
> If you need to (for instance) mark the start of a new day when you are
> displaying hours and minutes, so that it could be something like:
> 23:30  23:50  02/23  00:10  00:30  00:50  01:10
> then the approaches I suggested won't work.  The only way I could think of
> to do that would require a routine that processed the whole range for
> month markers, then each month (sub)range for day markers then each day
> (sub)range for hour markers and each hour (sub)range for minute markers
> and finally each minute (sub)range for seconds markers. This is a typical
> recursive routine. At any level there may be only one sub-range  - ie, the
> span is less than one unit of the current range.  Or, there could be
> several sub-ranges, each one of which is then processed recursively to see
> if it needs intermediate markers.  Recursion would stop as soon as there
> was no room for a marker, or when it got to the seconds level.  The
> original algorithm would work for placing the markers, as each subrange
> would appear to be a complete graph. Doing it from the top down (months,
> then days then hours etc) can also take care of the problem that (for
> example) an hour:minute marker of 00:00 should actually be promoted to a
> mm/dd marker, as this marker will have already been inserted at the higher
> recursion level.  But this is becoming very complex code.  Because it
> considers the whole range it could not be done as points are placed, but
> only after the extent of the graph was known. I don't think you could do
> this if it was a moving graph without having the labels jump around
> unexpectedly.
>
> "David" <dw85745***@earthlink.net> wrote in message
> news:uEdINiRlJHA.1288@TK2MSFTNGP02.phx.gbl...
>> Mr Hahn:
>>
>> Thanks for response.  I am using VB6 not Net but the logic should be the
>> same whether you are using TextWidth or MeasureString.
>>
>> The key area I'm trying to address is the "Number of Labels" placed
>> across the screen.  In your original post you aptly point out:
>>
>> A.  Continue to the right, only labelling those points where the the
>> label position (starting point) is a certain distance beyond the end of
>> the previous label.
>>
>> and
>>
>> The first label is the first point which has a label start of 0 or
>> greater. The next point is the first point that has a label start of the
>> end of the previous label plus an allowance for spacing.
>>
>> I do the above as noted.
>>
>> -------------------
>> Where the issue lies is this.
>>
>> As I spin through my display loop I put down my datapoint, then I check
>> to see if that point is the beginning of a day, if so I place "mm/dd" at
>> that location, determine the width of those characters (5) and calculate
>> where the next label can be placed.  I then lay down datapoints until I'm
>> => that spacing, then place another label for the next point "hh:mm".  I
>> then calculate that that label width(5), determine where the next label
>> point can be placed and continue to loop.
>> This places a lot of labels.  If display time period changes  to days for
>> example, I mark every month and then label every seventh day.
>>
>> I could have a variable which adjusts the number of dependent labels
>> "hh:mm" or "day", but I'm looking for some way to adjust this
>> automatically
>>
>> Any ideas?
>>
>