I am using dynamic data display library to view a dynamic integer value coming in at frequent intervals and plotting it as a linegraph ('line1') onto a chartplotter named 'plotter'. What I want is to have a way to erase all the data from the chartplotter when I uncheck the checkbox and start plotting again once i check it back. I thought I might be able to accomplish it with plotter.Children.Remove(line1), but it does not erase the old data. Instead it plots over the old data again and I have double data lines. Here is the code example (includes some pseudo codes) that I have so far.
ObservableDataSource<System.Windows.Point> source1=new ObservableDataSource<System.Windows.Point>();
LineGraph line1=new LineGraph(source1);
line1.Name = "Data1";
int i=0;
start a timer to CaptureData...
CaptureData(....,...)
{
if a CheckBox is checked...()
{
if (i == 0)
{
plotter.Children.Add(line1);
}
double graph_x = Convert.ToDouble(i);
double graph_y = Convert.ToDouble(datapoint that I have);
System.Windows.Point p1 = new System.Windows.Point(graph_x, graph_y);
source1.AppendAsync(Dispatcher, p1);
i++;
}
}
Once the checkBox is unchecked
{
if (i != 0)
{
i=0;
plotter.Children.Remove(line1);
}
}
}
This is the linegraph that I am getting now with data starting to plot again at the beginning, but the old data is still hanging in there. What I want to achieve is a clean new graph without the old line present. I don't have the minimum points to post an image. So please see the image here: https://dl.dropboxusercontent.com/u/49447650/test5.png
You have to clear the source :
source1.RemoveAll(typeof(Point));
Related
I'm using OxyPlot to show a data chart and to allow the user to select an interval of data he wants to do calculation on.
It looks like this:
Now, I would like the user to be able to set the data interval used for calculation himself by resizing the chart. For example, if he resized the chart on this particular interval it would only take the points located between the furthest left and the furthest right on screen.
I already found the event that triggers whenever the chart is resized :
plotModel.Updated += (s, e) =>
{
//reset interval used for calculation
};
What I couldn't find in OxyPlot documentation is a way to retrieve a certain set of points currently shown. It doesn't need to be points in particular, I could also use only the x components of each extremum.
You could use Series.GetScreenRectangle().Contains() method after transforming your points using the Transform() method to detect if the point is currently in display.
For example,
model.Updated += (s,e)=>
{
if(s is PlotModel plotModel)
{
var series = plotModel.Series.OfType<OxyPlot.Series.LineSeries>().Single();
var pointCurrentlyInDisplay = new List<DataPoint>();
foreach (var point in series.ItemsSource.OfType<DataPoint>())
{
if (series.GetScreenRectangle().Contains(series.Transform(point)))
{
pointCurrentlyInDisplay.Add(point);
}
}
}
};
You are iterating over the point collection and verifying if the Transformed point (Transform method transform DataPoint to screen point) falls within the Screen Rectangle used by the series.
Update
If you have used Series.Points.AddRange()/Add() for adding points instead of Series.ItemSource, use the following for retrieving points.
foreach (var point in series.Points.OfType<DataPoint>())
{
if (series.GetScreenRectangle().Contains(series.Transform(point)))
{
pointCurrentlyInDisplay.Add(point);
}
}
I'm trying to add a Chart control dynamically to a Form (using C#, this should all be .NET 4.0), but it's always blank (only the background color shows). I tried the same code in a Form that already has a control and it works, so I imagine it's some initialization function I should call (I tried Invalidate() on the control and Refresh() on both control and the panel it's being placed in, made no difference). I went through the few similar posts I found, tried throwing in any other commands they used (BeginInit() is from one such post) but no luck so far. Any ideas?
BTW I want to display 6-9 charts (position, speed and acceleration in 3D space) so I'd rather add them dynamically than have 9 sets of assignments. Here's the code that adds the charts to the panel:
foreach (KeyValuePair<string, List<double>> p in b.storedValues)
{
Control c = getChartForData(p);
panel1.Controls.Add(c);
c.Invalidate();
c.Refresh();
break;
}
And the function that creates each chart:
private Chart getChartForData(KeyValuePair<string, List<double>> data)
{
Chart c = new Chart();
((System.ComponentModel.ISupportInitialize)c).BeginInit();
c.Series.Clear();
c.BackColor = Color.White;
c.Height = 300;
c.Width = 500;
c.Palette = ChartColorPalette.Bright;
Series s = new Series(data.Key);
s.ChartType = SeriesChartType.Spline;
double maxValue = 0;
//NOTE: Going logarithmic on this, too big numbers
for (int i = 0; i < data.Value.Count; i++)
{
maxValue = Math.Max(Math.Log10(data.Value[i]), maxValue);
}
for (int i = 0; i < data.Value.Count; i++)
{
s.Points.AddXY(i,Math.Log10(data.Value[i]) * c.Height / maxValue);
}
c.Series.Add(s);
return c;
}
Many thanks in advance.
When you create a Chart yourself, in code, it does not contain any ChartArea.
Therefore, nothing is displayed.
I'm guessing that the designer generates some code to initialize a default chart area when you drag and drop a chart control onto the form.
Also, you should really let the chart control handle the layout, instead of calculating the desired position of each point based on the height of the chart control.
I would go as simple as possible to get something that's working, and then you can tweak the range of the axis afterwards. You can also set an axis to be logarithmic.
Start with trying out this minimal version, and make sure that displays something, before you complicate things. This works for me.
private Chart getChartForData(string key, List<double> data)
{
Chart c = new Chart();
Series s = new Series(key);
s.ChartType = SeriesChartType.Spline;
for (int i = 0; i < data.Count; i++)
{
s.Points.AddXY(i, data[i]);
}
c.Series.Add(s);
var area = c.ChartAreas.Add(c.ChartAreas.NextUniqueName());
s.ChartArea = area.Name;
// Here you can tweak the axis of the chart area - min and max value,
// where they display "ticks", and so on.
return c;
}
I have a C# webforms page where I want to drag html elements into a telerik radeditor. This part is working as expected except that when you drag an element onto the editor I want the cursor position in the radeditor to follow the mouse. It is set up similar to this demo on Teleriks web site. Except I am using a listview instead of treeview.
http://demos.telerik.com/aspnet-ajax/editor/examples/treeviewandeditor/defaultcs.aspx
I have tried simulating clicks on the radeditor to move the cursor, but no luck there. Any ideas?
Edit:
I have made a semi-working solution last week. Its far from perfect but I decided to share it in case some one else wants to make it better.
function controlDragging(sender, args) {
var event = args.get_domEvent();
var editor = $find("radEditLayout");
if (isMouseOverEditor(editor, event)) {
var x = event.pageX - event.offsetX;
var y = event.pageY - event.offsetY;
var node = editor.get_document().elementFromPoint(x, y);
if (node) {
setCaret(editor, node, 0);
}
}
}
function setCaret(editor, element, position) {
var selection = editor.getSelection(),
range = selection.getRange(true);
if (range.setStartAfter) {//W3 range
range.setStartAfter(element);
}
else { //IE7/8 textRange
range.moveToElementText(element);
range.moveStart('character', position);
}
range.collapse(true);
selection.selectRange(range);
}
function isMouseOverEditor(editor, event) {
return $telerik.isMouseOverElementEx(editor.get_contentAreaElement(), event);
}
Any more suggestions??
Perhaps you will be able to figure out something with ranges, but I am not sure exactly how as I have not used them. Here are the basics on getting an already selected range http://www.telerik.com/help/aspnet-ajax/editor-getselection-1.html and here is how to get the document object so you can use ranges in it: http://www.telerik.com/help/aspnet-ajax/editor-getting-reference-to-radeditor-documentobject.html. Perhaps this can help you get started but I think it will be a lot of work: How to set caret(cursor) position in contenteditable element (div)? because I am not sure how you can calculate the position at which you want the cursor from the mouse coordinates.
I know this post is old but perhaps others can benefit from it. Here's a snippet that helped me drop at a random position in the RadEditor content area. It does not involve moving the cursor position.
kendoDropTarget({
drop: function(e) {
debugger;
var top = e.draggable.drag.y.location - $('.k-content').offset().top;
var left= e.draggable.drag.x.location - $('.k-content').offset().left;
element.css({
top: top + 'px',
left: left + 'px'
});
$('.overlay').remove();
$('.k-content').contents().find('body').html($('.k-content').contents().find('body').html() + $(element).outerHTML());
}
I'm hoping someone can help me out here. My ultimate goal with this code is to extract the color of the sweater I am wearing. Like the title suggests, I'm trying to exctract RBG values from a certain Skeleton point (ie. skeleton.Joint[JointType.Spine].Position). I do this using the following mapping:
All of the following code is within the SensorAllFramesReady event:
private void SensorAllFramesReady(object sender, AllFramesReadyEventArgs e)
{
Skeleton[] skeletons = new Skeleton[0];
using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
{
if (skeletonFrame != null)
{
skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
skeletonFrame.CopySkeletonDataTo(skeletons);
}
}
if (skeletons.Length != 0)
{
foreach (Skeleton skel in skeletons)
{
if (skel.TrackingState == SkeletonTrackingState.Tracked)
{
colorPoint = this.SkeletonPointToColor(skel.Joints[JointType.Spine].Position);
}
}
}
}
private Point SkeletonPointToColor(SkeletonPoint skelpoint)
{
ColorImagePoint colorPoint = this.sensor.CoordinateMapper.MapSkeletonPointToColorPoint(skelpoint, ColorImageFormat.RgbResolution640x480Fps30);
return new Point(colorPoint.X, colorPoint.Y);
}
I assign the returned Point to a variable "ColorPoint", and here is how I (somewhat successful) extract the RBG values:
using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
{
if (colorFrame != null)
{
int arrayLength = colorFrame.PixelDataLength;
this.colorPixelData = new byte[arrayLength];
colorFrame.CopyPixelDataTo(this.colorPixelData);
blue = (int)colorPixelData[(int)(4* (colorPoint.X + (colorPoint.Y * colorFrame.Width)))+0];
green = (int)colorPixelData[(int)(4 * (colorPoint.X + (colorPoint.Y * colorFrame.Width))) + 1];
red = (int)colorPixelData[(int)(4 * (colorPoint.X + (colorPoint.Y * colorFrame.Width))) + 2];
}
}
I then draw an ellipse on my Windows Form window using the retrieved RBG values. Now this works, kind of. I do get a color which resembles the color of the sweater I'm wearing, but even if I do my best to stand very still the color is always changing. It's almost as if I'm getting random RBG values within a certain range, and only the range is dictated by the color of my sweater. Why is this? Is there another way I should be solving this problem?
Thank you for reading!
EDIT: I apologise for the formatting, this is my firs time submitting a question and I realise the formatting in the first code block is a bit off. The SkeletonPointToColor method is naturally not within the SensorAllFramesReady method. My apologies
First of all I really recomend you have a look at the Coding4Fun Kinect Toolkit which provides many useful functions for dealing with the Kinect data. There is a for instance an extension for returning a bitmap named ToBitmapSource() which should be of use.
Another observation is that without using some algorithm to get an average of the color values received it's quite normal to have the color values jump around. Also not confident that you can expect the skeleton and image frames to be 100% in sync.
This post corresponds to your answer on my previous post...
Before I upload a simple project for you, let me try something else: I noticed that when I swap the Points Series with a ColorGrid series the same thing happens, BUT, when I then (with the ColorGrid Series) use "MyColorGrid.YValues[gridPosition] = val" instead of MyColorGrid.Add(X, Y, Z) then it works. Is there a way I can use the Points Series in the same way, ie, allocate all the points the first time, and then just use XValues[idx] = x, and YValues[idx] = y to update the points? The problem seems to happen when I use the Add method, together with the Clear method. When I just update the values with XValues and YValues etc. the problem seems to be solved! The thing is, I can not get it to work on a Points Series...it was easy with the ColorGrid Series:
for (int r = 0; r < 128; r++)
{
for (int d = 0; d < 128; d++)
{
MyColorGrid.YValues[d * 128 + r] = some_value;
}
}
MyColorGrid.BeginUpdate();
MyColorGrid.EndUpdate();
Question 1: How do I achieve the same for the Points Series?
Question 2: If I succeed, how do I clear/delete points, without again having to "Add(x, y)" them afterwards?
Question 3: Is this the best way to use BeginUpdate/EndUpdate? Whats the difference? In general, what are the differences between all the available update methods, and how do I choose the correct one?
A few examples:
MyColorGrid.RefreshSeries
MyColorGrid.Repaint
MyTChart.Refresh
MyTChart.AutoRepaint
Regards
JD
Question 1: How do I achieve the same for the Points Series?
I suggest you use a similar code as next that works in correct way when you update the points.
Steema.TeeChart.Styles.Points points1;
Steema.TeeChart.TChart tChart1;
Random rnd;
public Form1()
{
InitializeComponent();
tChart1 = new Steema.TeeChart.TChart();
this.Controls.Add(tChart1);
tChart1.Aspect.View3D = false;
tChart1.Height = 400;
tChart1.Width = 500;
tChart1.Dock = DockStyle.Bottom;
points1 = new Steema.TeeChart.Styles.Points(tChart1.Chart);
rnd = new Random();
InitializeChart();
}
private void InitializeChart()
{
for (int i = 0; i < 128; i++)
{
points1.Add(i, rnd.Next(100));
}
tChart1.Refresh();
}
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 128; i++)
{
points1.XValues[i] = i+1;
points1.YValues[i] = rnd.Next(100);
}
points1.BeginUpdate();
points1.EndUpdate();
}
Question 2: If I succeed, how do I clear/delete points, without again having to "Add(x, y)" them afterwards?
I suggest you use the method SetNull() to make null the point as you don't want. You can do the same as next line of code:
points1.SetNull(3);
Question 3: Is this the best way to use BeginUpdate/EndUpdate? Whats the difference? In general, what are the differences between all the available update methods, and how do I choose the correct one? A few examples:
About BeginUpdate/EndUpdate:
The BeginUpdate method recalculates the function just one time, when finished adding points and the EndUpdate method is necessary used with .BeginUpdate to recalculate the function just once when finished adding points.
Therefore, you must use the both methods when you decide use BeginUpdate to update your series.
About other methods:
The differences between methods are explained by its definition that is found in help documentation and you can see in next lines:
Series.RefreshSeries: The RefreshSeries method notifies all dependent Series to recalculate their points again. Each Series has a DataSource property. When DataSource is a valid Series or DataSet component, Series get all point values from the DataSource and adds them as Series points. The RefreshSeries method forces the Series to Clear and get all points again from the DataSource component. The Refreshing process traverses the Series tree recursively
Series.Repaint: This Series method forces the whole Parent Chart to Repaint. You don't normally call Repaint directly. It can be used within derived TChartSeries components when changing their properties internally .
TChart.Refresh: Forces the control to invalidate its client area and immediately redraw itself and any child controls.
TChart.AutoRepaint: Use AutoRepaint false to disable Chart repainting whilst (for example) adding a large number of points to a Chart Series. This avoids repainting of the Chart whilst the points are added. AutoRepaint may be re-enabled, followed by a manual Repaint command when all points are added.
I hope will helps. If you have any questions please let me know.
Thanks,