Dynamic-Data-Display / Getting x-coordinate of user input - c#

My program is basically about analyzing videos.
A major part is to plot a diagram showing (f.e.) brightness per frame on y-axis and every frame number on x-axis. Because the program is written in C# and uses WPF, D³ was the way to go for plotting.
Now the user might see a peak signal in the diagram and wants to look on that single frame to understand why it's so bright (it might be just natural, or an encoding-artifact).
There comes my question: The most intuitive way for the user to click on the diagram where the peak is, which jumps the video preview (other GUI element) right to that frame. So I need the x-coordinate (=frame number) of the user click on the diagram.
It is possible to manually analyze the mouse-input event, but that would take much work (because the x-axis is different for each video and the entire diagram can be resized, so absolute coordinates are a no go).
But maybe something similar is already implemented by D³. I searched the documentary, but didn't find anything useful. The only piece of information was using a "DraggablePoint", but that's where the trail goes cold.
Does someone of you know how to get the x-coordinate without much work?

It sure is possible! The way that I have done it in the past is to add a CursorCoordinateGraph object to my plotters children, and it automatically tracks the mouse position on the graph in relation to the data. You can turn off the visual features of the CursorCoordinateGraph and use it for tracking only. Here's what it would look like:
CursorCoordinateGraph mouseTrack;
plotter.Children.Add(mouseTrack);
mouseTrack.ShowHorizontalLine = false;
mouseTrack.ShowVerticalLine = false;
And your mouse click event would look like this:
private void plotter_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point mousePos = mouseTrack.Position;
var transform = plotter.Viewport.Transform;
Point mousePosInData = mousePos.ScreenToData(transform);
double xValue = mousePosInData.X;
}
You can then use xValue and manipulate it however you would like to achieve your desired effect.

Related

Is there a way in a Blazor Server app to get mouse coordinates clicked

I am trying to get motivated to move one of my open source projects called Transparency Maker from Windows Forms to Blazor, so I can put the app online.
All of the image editing is done via text in a language called BQL (Bitmap Query Language) which is very similar to SQL.
The one thing I don't know how to do in Blazor is get the x, y position of where the image is clicked. Windows Forms makes this very simple, although I have to do some scaling.
Is there a JavaScript way of doing this and bringing it into Blazor?
This is a feature I have to have, or writing a query like this is impossible for the user to know what to type:
Update
Set Adjust Red -200
Where
X Between 1700 2591
Y Between 1930 2110
Total > 500
Notice the White part of the socks in the second image, only the white was changed because the Total (Red + Blue + Green) has to be greater than 500 to perform the adjustment.
Thanks if this is possible to get the position clicked?
I think more people might appreciate this tool once it is online. As it is, "selling" free software is actually harder than it should be.
Transparency Maker
https://github.com/DataJuggler/TransparencyMaker
I am posting an answer thanks to the help from dani (if you posted your answer here, I could mark it as the answer).
I had to do two things to make this work:
Add a using statement for
using Microsoft.AspNetCore.Components.Web;
I added the EventCallback e parameter, and I didn't have to change anything else.
public void Button_Clicked(MouseEventArgs e)
{
double x = e.ClientX;
}
I will probably have to write some trial and error code to go from where the image is located, to find what pixel was actually clicked, but now I am confident I can do this.
Many thanks Dani. I will name a hospital after you some day.

Horizontal Scroll Bar in Oxyplot WPF

I'm trying to implement a utility for showing throughput over time in a system, and am using Oxyplot to visualise the data.
Currently, zoom and pan are working as expected, but I would like some visual indication to the user which clearly shows whether the graph can be zoomed or panned.
After ditching the idea of using a scroll bar (being neither able to accurately get the position of the visible section of the graph, nor correctly position the thumb of the scroll bar releative to the chart), I have settled on using icons to show whether there is any data on the chart which is hidden to the left or rightmost side.
I would like these icons to work as buttons which allow the user to page left and right on the graph, however as with all things OxyPlot related, the implementation is far more complex than it first seems.
I'm using the WPF implementation, which uses a ViewModel representing the overall data set, with each series item represented by its own model.
This effectively renders almost every tutorial useless as the WPF implementation is significantly different to the basic OxyPlot package.
Currently, the code behind in the view handles the click on the page left/right buttons. I cannot put this in my ViewModel as it must interract directly with the PlotControl object.
private void btnPageRight_Click(object sender, RoutedEventArgs e) {
CategoryAxis axis = (CategoryAxis)PlotControl.ActualModel.Axes[0];
double xAxisMin = axis.ActualMinimum;
double xAxisMax = axis.ActualMaximum;
double visibleSpan = xAxisMax - xAxisMin;
double newMinOffset = xAxisMax + visibleSpan;
PlotControl.Axes[0].Minimum = newMinOffset;
PlotControl.Axes[0].Maximum = newMinOffset + visibleSpan;
PlotControl.ActualModel.InvalidatePlot(true);
}
As it stands, the above code throws no errors, but it does not work either.
If anybody can advise a possible way to make OxyPlot scroll to a given position using just code behind, I would be grateful.
As a last resort, I have pondered trying to simulate a mouse drag event to make this finicky beast behave.
I find the need to work around the problem in that way quite offensive, but desparation leads to odd solutions...
In case anybody else runs into this issue, the following snippet will scroll the graph in pages based on the number of columns visible on the graph at the time.
The snippet takes the number of visible columns as the viewport, and will move the visible area by the viewport size.
Although this applies to the WPF implementation, the only way I could find to make this work was to run this method from the code behind in the View containing the OxyPlot chart.
This should work correctly regardless of the zoom amount at the time.
The CategoryAxis reference must be obtained from the ActualModel as the WPF.Axis does not provide the ActualMinumum and ActualMaximum needed to calculate the viewable area.
The visibleSpan in this case represents the number of columns, with panStep denoting the amount to pan by in pixels.
private void ScrollInPages() {
//To zoom on the X axis.
CategoryAxis axis = (CategoryAxis)PlotControl.ActualModel.Axes[0];
double visibleSpan = axis.ActualMaximum - axis.ActualMinimum;
double panStep = 0;
//Scrolling the chart - comment out as appropriate
//Scroll right one page
panStep = axis.Transform(0 - (axis.Offset + visibleSpan));
//Scroll left one page
panStep = axis.Transform(axis.Offset + visibleSpan);
axis.Pan(panStep);
PlotControl.InvalidateFlag++;
}

Tangram puzzle application

I am trying to create a WPF application using C# to run on Pixelsense that is basic version of the tangram puzzle. I am able to draw my 7 shapes and translate and rotate them all around the screen.
Could anyone give me advise regarding how I should go about saving the pattern (with shapes in specific positions and orientations) so that when a user creates the pattern next time, the application can match it to the saved one and tell the user if it's correct.
It's a pattern matching and recognition problem that I am trying to solve.
I have been stuck on this for a while now :(
Define the solution as a collection of objects with shapeType, position, and orientation properties. Have the solution include one shape at position 0, 0 and an orientation of 0. Now loop over all the shapes the user has actually placed to find the ones with a shapeType that matches the shape your solution has at 0,0,0. Calculate the position and orientation of every other shape relative to where the user put this one. Compare those values to the rest of your solution. You'll need to experiment with how much tolerance to allow because this stuff is not precise - to make the game fun, err on the side of having high tolerances. If needed, you can follow this up with some performance optimizations to only re-evaluate pieces that moved.
Hopefully you are using physical shape prices with tags on them instead of this purely a virtual game. I always wanted to build this when I was on the Surface team but it never happened. One challenge you will run into is defining how the tag's position/orientation relates to the actual shape. If you'll be putting tag stickers on multiple tangram sets, you almost certainly won't get the on precisely the same each time so you may need to add a "calibration" mode to your app (have the user place each piece in a specific spot and then push a button so you can record where the tag is relative to those spots). The TagVisualizer WPF control should help a lot for building your UI - definitely look into using it (this scenario was top of mind when we designed that API). The default behavior of that control (if you tell it the ID of a tag to look for but not how to visualize it) is a "crosshair" that can help you find tune your offset values.
Good luck! If you wouldn't mind recording a YouTube video when you are done and posting a comment here linking to it, I'd really appreciate that
You can use ObservableCollection or List of a custom class. That class can consist of various values such as position, orientation etc as properties.
When a new pattern is drawn or when the pattern change its position you can update that particular object stored in the collection. As you have all the details of the pattern(positions and orientation) you can iterate the for loop and check the position of the new pattern when added.

How to draw on an unfilled box on a video stream using the mouse

I am using dshownet(first time) and C#. I have got a sample to take the web cam input and display it on a form. I now need to draw a rectangle on top of the video stream using the mouse. (the intent is to track what is inside the box from there onwards).
I heard that there is something called VMR. So I went to the dshownet samples and went through them. I didnt find any samples that use the mouse to overlay a shape on the video stream. Someone on here suggested to use colorkey. Another person said to use GDI+ and mouse handling. I tried to compile the DXLogo sample but got this error :
Error 1 Cannot create an instance of the abstract class or interface 'System.Drawing.Image' C:\Documents and Settings\TLNA\Desktop\Final Year Project\Libraries\DirectShow library 2\DirectShowSamples-2010-February\Samples\Capture\DxLogo\Capture.cs 128 32 DxLogo-2008
for the code section:
if (fileName.Length > 0)
{
m_Bitmap = new Image(fileName); // error happened here
Rectangle r = new Rectangle(0, 0, m_Bitmap.Width, m_Bitmap.Height);
m_bmdLogo = m_Bitmap.LockBits(r, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
}
I know that I must go through the Bitmap9 Interface. But I really dont know where to start. Should I read the Directshow API docs.
btw I also have the book Programming Microsoft Directshow for digital video and television. I started reading that book and stopped after a few pages since the code is mainly in C++. Should I continue to read this is book ? How can I accomplish the certain mentioned tasks in C# ?
Any suggestions as how to draw on the video. Some useful links(tutorials) would be helpful.
Many Thanks
Tlna
I'm not sure why the DirectShow sample doesn't compile, but you may be able to change the problem line:
m_Bitmap = new Image(fileName);
to this:
m_Bitmap = new Bitmap(fileName);
and get it to work.
You're actually facing a pretty difficult problem here. DirectShow renders a video by drawing a series of still frames to a device context (like a PictureBox or a Form, or even the screen) many times a second (depending on whatever the frame rate is). You (as a programmer) can also (easily) render graphics directly to this same device context.
However, in order to make your drawn box appear over top of a running video, your code needs to draw the rectangle immediately after DirectShow draws each frame of the video; otherwise, the next frame will obliterate your rectangle. DirectShow objects probably have some sort of frame rendering event that you can handle, and then inside the event handler you just re-draw your box (based on the initial and current mouse coordinates, which you can get from the MouseDown and MouseMove events of whatever control you're drawing on).
Update: I just took a look at my code from when I was playing around with DirectShow.NET, and it looks like there is an event (DsEvCode.Repaint) that you could hook into and use to draw your box.
I haven't looked at the code sample you're working with, but do a search and see if you can find an OnGraphNotify() method in your code, you should be able to add something like this:
if (code == DsEvCode.Repaint)
{
// draw the box here
}
Presumably, this event is fired after each frame of the video is rendered, so if you redraw your box here every time it will appear as if the box is persisting.

mouse followed drawing in C#

I want to to make a shared drawing board in C#. This means that two people connected via a TCP connection can draw on this board. The idea (for now) is that people can click on the screen and draw. What do you think is the best method for this?
It's easy enough to draw a dot when the user clicks on a certain spot, but it gets a little more complicated when the user drags the mouse, where you need to draw a line between the last point and the current. Also that doesn't work so well, so I draw a dot where the line starts to improve things a bit, but it's not that good.
Lastly, I need to also send this over TCP, so I need to distinguish between the two. I hoped that I could just send points and have it draw it on the other side, but it seems it wouldn't work. Any ideas except also sending the type?
drawing http://img193.imageshack.us/img193/9697/drawingw.png
EDIT:
ok, I'm going with a IDrawingArgument interface that has Dispatch(myForm), and basically does double dispatch, so it solves the TCP problem (going to serialize/deserialize it).
Lines are still a bit bulky.
One little tip... on your mousemove event. keep a flag that wont fire the event again until the last event that set the flag turns it off. i.e.:
bool isDrawing = false;
public void myCanvas_MouseMove(object sender, EventArgs e)
{
if(!isDrawing)
{
isDrawing = true;
// Do drawing here
isDrawing = false;
}
}
This helped me a lot when doing drawing in a mousemove event.
Dots:
(x,y),(x2,y2),(x3,y3)
Lines:
(x,y,x2,y2),(x3,y3,x4,y4)
Thus, the format is a list of tuples. Tuples of size 4 are lines, of size 2 are points. Note that if your system gets more complicated, you'll really regret not just doing something like:
Dots:
D(x,y),D(x2,y2),D(x3,y3)
Lines:
L(x,y,x2,y2),L(x3,y3,x4,y4)

Categories

Resources