Page 1 of 1
Add scalable image to gauge chartview (Xamarin Forms)
Posted: Tue Dec 15, 2020 9:51 pm
by 18290001
Using = Steema.TeeChart.NET.Xamarin.Forms v4.2020.10.26
Development platform = Visual Studio 2019 Pro v16.7.7
Target device = Android 6.0 (API 23) to API 10.0 (API 29) smallest res = 480x800
I have a requirement to draw an image on top of a circular gauge at a position relative to the gauge and for the image to scale in size when the ChartView changes size, but to keep it's position relatively within the circular gauge (chart view).
Using information from other posts in the forum, and the TeeChartNetExamples code, I use the Chart_AfterDraw event to draw the image, but my issues are...
1) How to keep the image size scaled relative to the gauge
2) How to position the image, but I would be able to do this if I could define the image size
I have written a test app, showing the same user control in 2 different sizes.
- GaugeTestApp.png (84.29 KiB) Viewed 23948 times
Code...
public ImageSource ImageSource { get; set; }
private void Chart_AfterDraw(object sender, Steema.TeeChart.Drawing.Graphics3D g)
{
var img = new Image() { Source = ImageSource };
var xpos = g.ChartXCenter - (CircularGauge.XRadius / 2);
var ypos = g.ChartYCenter;
// WORKING
g.Draw(xpos, ypos, img);
// NOT WORKING
//g.Draw(new Rectangle(xpos, ypos, 12, 12), img, Steema.TeeChart.Drawing.ImageMode.Stretch, false);
}
I assume the solution is in one of the g.Draw overloads but I can't find the correct syntax.
The target look is this...
- Target.jpg (5.59 KiB) Viewed 23948 times
All feedback & assistance appreciated
Re: Add scalable image to gauge chartview (Xamarin Forms)
Posted: Thu Dec 17, 2020 9:11 am
by Pep
Hello,
just inform to you, that we're looking at it, and doing some tests in order to reproduce the problem , and we'll back to you with an answer as soon as possible.
As a question to you, what does it happens when you use the :
// NOT WORKING
//g.Draw(new Rectangle(xpos, ypos, 12, 12), img, Steema.TeeChart.Drawing.ImageMode.Stretch, false);
Do you have a simple exmaple with which we can reproduce the problem as is ?
Thanks
Re: Add scalable image to gauge chartview (Xamarin Forms)
Posted: Thu Dec 17, 2020 10:08 am
by Pep
Hello,
ok, i've been able to reproduce the problem here. It's bug. It has been added on our bug list so it can be addressed into the next maintenance releases.
http://bugs.teechart.net/show_bug.cgi?id=2394
The problem happens once we try to use the Draw method in conjnction with the stretch mode. As a workaround until the problem is fixed, you'd have to use the image mode as "Normal" and resize the image externally, just before to draw over the Chart.
Code: Select all
// first resize the image to desired rectangle size ..
chart.Chart.Graphics3D.Draw(new Rectangle(0, 0, 120, 120), bImage, Steema.TeeChart.Drawing.ImageMode.Normal, false);
Re: Add scalable image to gauge chartview (Xamarin Forms)
Posted: Wed Jan 06, 2021 11:36 pm
by 18290001
Hello,
Thankyou for your help.
I have now re-written my image overlay code, as suggested, and I now resize the image in separate code before using the following line to draw the image...
g.Draw(new Rectangle(xpos, ypos, imgX, imgY), img, Steema.TeeChart.Drawing.ImageMode.Normal, false);
I can now successfully re-size the image relative to the circular gauge and position it as needed (see image)
- GaugeTestAppWithBattery.png (71.79 KiB) Viewed 23692 times
However, the issue I now have is that the image is not always shown. When the app starts, the Chart_AfterDraw event fires and the code to draw the image is run but the image is not shown. If I click the "DRAW IMAGE" button, which runs the same code, then the image is drawn OK.
Randomly pressing on the gauge, which causes the Chart_AfterDraw event to fire, does sometimes result in the image being drawn but on the next press of the gauge the image disappears.
Obviously, within the main production App, I need the image to draw without having to manually press a button (e.g. when the app is backgrounded & then resumes)
I have attached a zip file with the small sample solution which demonstrates this issue.
Again, all assistance is appreciated as I am very close to a workable solution now.
Re: Add scalable image to gauge chartview (Xamarin Forms)
Posted: Thu Jan 07, 2021 7:04 am
by Pep
Hello,
sure, let me check the example you've attached and back to you asap.
Most likely it can be solved by calling to the draw method at the OnBeforeDrawSeries event, but let me check and see what happens.
Re: Add scalable image to gauge chartview (Xamarin Forms)
Posted: Tue Jan 12, 2021 7:58 pm
by 18290001
Hello,
Appreciate that you probably have not had chance to look into this yet & reply, but as I am being asked to find a resolution to this issue I've been trying some more possible solutions based on your suggestion.
I've tried all the "Before" events available (i.e. BeforeDraw, BeforeDrawAxes, BeforeDrawSeries) and they throw an exception because my code to calculate the image size & position is based on the size & position of the Circular Gauge (Chart Series) which has not usually been created/drawn at that point.
Code: Select all
double imgX = CircularGauge.YRadius / 2;
double imgY = imgX;
var img = new Image();
byte[] resizedImage = DependencyService.Get<IImageResizer>().ResizeImage(ImageFileName, imgX, imgY);
img.Source = ImageSource.FromStream(() => new MemoryStream(resizedImage));
var xpos = g.ChartXCenter - (imgX / 2);
var ypos = g.ChartYCenter + ((CircularGauge.YRadius / 2) - (imgY / 2));
g.Draw(new Rectangle(xpos, ypos, imgX, imgY), img, Steema.TeeChart.Drawing.ImageMode.Normal, false);
It feels like the AfterDraw event is where I should be sizing the image and using the Graphics3D object to draw in on top of the chart, but as I mentioned before it usually does not appear.
Am I missing something obvious, because I would have thought that drawing images of certain sizes, in certain positions, on top of the chart control is quite a common request & I just can't make it work at the moment.
All help & feedback appreciated
Re: Add scalable image to gauge chartview (Xamarin Forms)
Posted: Tue Jan 12, 2021 9:45 pm
by Pep
Hello,
sorry fo delay on this anwer.
Just let you know that we're just looking at it. We hope to send a solution or just to publish a new version that fixes this problem asap.
We're looking for the best solution and will take a while. I hope we can have a this fix before the end of this week.
Thanks and appologies.
Re: Add scalable image to gauge chartview (Xamarin Forms)
Posted: Wed Jan 20, 2021 1:29 pm
by Pep
Hello,
We successfully tested a startup, once-only timer that loads the image everytime on startup but we have found in tests, as you noted, that the image can disappear unexpectedly at some screen paints. We think this is down to the environment and are following up on it. In the meantime we offer you this alternative that is based on TeeChart's Canvas methods and is robust under test. It is suitable to plot simple designs.
Code: Select all
private void DoDrawImage(Steema.TeeChart.Drawing.Graphics3D g)
{
System.Diagnostics.Debug.WriteLine("DoDrawImage");
double imgX = CircularGauge.YRadius / 2;
double imgY = imgX;
var xpos = g.ChartXCenter - (imgX / 2);
var ypos = g.ChartYCenter + ((CircularGauge.YRadius / 2) - (imgY / 2));
g.Brush.Visible = false;
g.Pen.Width = 9; //could scale this according to dimensions
//relative dimensions
double left = xpos + (imgX * 0.13);
double top = ypos + (imgY * 0.27);
double right = xpos + imgX - (imgX * 0.13);
double bottom = ypos + imgY - (imgY * 0.24);
double width = right - left;
double height = bottom - top;
double sigBar = width * 3 / 16; //define size for symbols
//top connectors
g.Pen.Color = Xamarin.Forms.Color.FromRgb(222, 222, 222);
g.Line(new Point(left + (width / 4) - (sigBar / 3), top - 4), new Point(left + (width / 4) + (sigBar / 3), top - 4));
g.Line(new Point(right - (width / 4) - (sigBar / 3), top - 4), new Point(right - (width / 4) + (sigBar / 3), top - 4));
//battery
g.Pen.Color = Xamarin.Forms.Color.FromRgb(201, 201, 201);
g.Rectangle(left,top,right,bottom);
//plus
g.Pen.Color = Xamarin.Forms.Color.FromRgb(218, 218, 218);
g.Line(new Point(left+(width/4)-(sigBar/2), top + (height * 3/8)), new Point(left + (width/4) + (sigBar / 2), top + (height * 3/8)));
g.Line(new Point(left+(width/4), top + (height*3/8) - (sigBar / 2)), new Point(left + (width / 4), top + (height * 3 / 8) + (sigBar / 2)));
//minus
g.Line(new Point(right - (width/4) - (sigBar / 2), top + (height * 3 / 8)), new Point(right - (width/4) + (sigBar / 2), top + (height * 3 / 8)));
}
Please, let me know if it helps.
Re: Add scalable image to gauge chartview (Xamarin Forms)
Posted: Wed Jan 20, 2021 8:30 pm
by 18290001
Hello,
Thank you for your answer. I have tested the proposed work-around solution here and it is working as you have described.
I should be able to use the g.Pen methods, as demonstrated, to create the images required, although it will mean more work than simply resizing an original image file.
The other graphic which I have to show is slightly more involved, so I may ask for the specification to be simplified so I can use the g.Pen methods to draw it easier.
- a_tempgauge.png (1.94 KiB) Viewed 23040 times
Obviously, I would still be interested to know the full answer, if you do find out how to reliably draw the resized original image correctly.
For now, thank you for your efforts with this issue.
Re: Add scalable image to gauge chartview (Xamarin Forms)
Posted: Thu Jan 21, 2021 1:34 pm
by Pep
Hello,
Obviously, I would still be interested to know the full answer, if you do find out how to reliably draw the resized original image correctly.
Sure, but for the moment we've not being able to find what is causing this behaviour.
The other graphic which I have to show is slightly more involved, so I may ask for the specification to be simplified so I can use the g.Pen methods to draw it easier.
Please find the code to generate the thermometer. The code was built up as required to plot the various parts of the thermometer. With a little time it can be tidied-up/rationalised a great deal. It will scale according to screen size and all the code to control its relative size, to make it larger or smaller depends on imgX. Changing imgX (eg. from (CircularGauge.YRadius / 4) to (CircularGauge.YRadius / 2)) will resize the whole plot. Growing/shrinking the value of ypos will then move it down or up.
Code: Select all
private void DoDrawImage(Steema.TeeChart.Drawing.Graphics3D g)
{
DrawThermometer(g);
}
private void DrawThermometer(Steema.TeeChart.Drawing.Graphics3D g)
{
System.Diagnostics.Debug.WriteLine("DoDrawImage");
double imgX = CircularGauge.YRadius / 4;
double imgY = imgX;
Xamarin.Forms.Color tColor = Xamarin.Forms.Color.FromRgb(221, 221, 221);
g.Pen.Width = 9; //could scale this according to dimensions
g.Pen.Color = tColor;
//thermometer
var xTPos = g.ChartXCenter - (imgX / 4); //horiz offset main bowl
var ypos = g.ChartYCenter + ((CircularGauge.YRadius / 2) - (imgY / 16)); //vertical offset
double left = xTPos;
double top = ypos;
double right = left + (imgX / 2);
double bottom = top + (imgY / 2);
double width = right - left;
double height = bottom - top;
//calc vert line start on arc
double lineXStart = (imgX / 4) * Math.Cos(50 * Math.PI / 180);
double lineYStart = (imgX / 4) * Math.Sin(50 * Math.PI / 180);
g.Arc(new Rectangle(left, top, right - left, bottom - top), 310, 280);
//left side
g.Line(new Point(g.ChartXCenter - lineXStart, top + (imgY / 4) - lineYStart), new Point(g.ChartXCenter - lineXStart, top + (imgY / 4) - lineYStart - (height*1.5)));
//right side
g.Line(new Point(g.ChartXCenter + lineXStart, top + (imgY / 4) - lineYStart), new Point(g.ChartXCenter + lineXStart, top + (imgY / 4) - lineYStart - (height*1.5)));
g.Arc(new Rectangle(g.ChartXCenter - lineXStart, top + (imgY / 4) - lineYStart - (height * 1.9), lineXStart*2, height * 0.8), 180, 180);
//Mercury
Steema.TeeChart.Drawing.ChartBrush tmpBrush = g.Brush;
g.Brush.Color = tColor;
g.Brush.Visible = true;
g.Ellipse(new Rectangle(left+(width*3/8), top+(height*3/8), width/4, height /4));
g.Line(new Point(left + (width/2), top + (height/2)), new Point(left + (width/2), top + (imgY / 4) - lineYStart - height));
g.Brush = tmpBrush;
//Scale markers
g.Line(new Point(g.ChartXCenter + lineXStart, top + (imgY / 4) - lineYStart - (height * 1.25)), new Point(g.ChartXCenter + lineXStart + (width/3), top + (imgY / 4) - lineYStart - (height * 1.25)));
g.Line(new Point(g.ChartXCenter + lineXStart, top + (imgY / 4) - lineYStart - (height * 0.75)), new Point(g.ChartXCenter + lineXStart + (width/4), top + (imgY / 4) - lineYStart - (height * 0.75)));
g.Line(new Point(g.ChartXCenter + lineXStart, top + (imgY / 4) - lineYStart - (height * 0.25)), new Point(g.ChartXCenter + lineXStart + (width/6), top + (imgY / 4) - lineYStart - (height * 0.25)));
//Symbol
g.Font.Size = height/3;
g.Font.Bold = true;
g.Font.Color = tColor;
g.TextOut(g.ChartXCenter - lineXStart - (width * 1.2), top + (imgY / 4) - lineYStart - (height * 1.7), "ÂșC");
}
Re: Add scalable image to gauge chartview (Xamarin Forms)
Posted: Thu Jan 21, 2021 10:40 pm
by 18290001
Hello,
This new code for the thermometer graphic is excellent & far more than I expected you to provide.
I have now integrated the battery & thermometer graphic drawing code into my main App (see screenshot below) & will be able to move this into production.
- Gauge Screenshot (with drawn graphics).png (69.82 KiB) Viewed 22989 times
Many thanks for your commitment in helping to resolve this issue
Re: Add scalable image to gauge chartview (Xamarin Forms)
Posted: Fri Jan 22, 2021 7:37 am
by Pep
Hello,
I'm glad to hear you like it.
Thanks !