Draw and fill a signal - c#

I would like to draw and then fill a signal using graphics.drawcurve and graphics.fillclosedcurve as following:
Graphics
gX = drawPanel.CreateGraphics();
Pen pen1 = new Pen(Color.Black);
Brush be = new SolidBrush(Color.Gray);
gX.DrawCurve(pen1, pointArray1, 0.01F);
gX.FillClosedCurve(be, pointArray1);
Although there is no minus in the plotted data I got some filled curved at the minus side of the curve (due to interpolation?) as following:
How can I get rid of these artifacts?
Thanks in advance!

Do not use DrawCurves to plot real data!
They look nice and are useful when creating a freehand plot of your mouse movements.
But when plotting data they are not so good as they tend to overdraw esp. when the direction changes quickly.
See here for an instructive example of overdrawing! Setting a Tension is a way to limit the problem; but it will also limit the smoothness of the lines..
The solution there uses Beziers, but this not what you should do!
With the great number of dara points you seem to have I suggest you stick to DrawLines & FillPolygon instead; they still should look rather smooth..

Related

How can I draw a Line animation to outline various shapes?

I am trying to draw a line animation outline various shapes as in the image below. I am very well aware that it's best practice that I mention what I've been able to achieve to get specific help, but I am not sure where to begin, just that I know that using a Line Renderer could be a good approach to achieving this. That said, how can I achieve this?
UPDATE
I think I didn't explain a few things clearly enough. I am interested in animating the outline of objects without arrows, just a line traced round the outline like the image below:
I would do the following: (pseudocode, untested)
For every prefab or gameobject, store a List of edges that define your outline.
I wouldn't recommend using the mesh's edges, it's probably better to have a specific predefined list of edges per shape to avoid the inner edges of the object. Every entry in the list is defined by two Vector3's which are the two vertices.
List<Vector3[]> outline = new List<Vector3[]>();
Now, you have many ways to actually draw the arrows, like having them as individual gameobjects (probably not a good idea), particle system, or just drawn automatically from the parent objects update function. I would recommend the latter.
Now you would store a bunch of floats that define where your arrows are
public List<float> arrow_locations = new List<float>();
//adding one arrow
arrow_locations.Add(0.0);
//now in the update function of your parent object, update the arrow locations
private float cycle = 0.0f;
void Update()
{
float segment_size = 360.0f/outline.Count;
for(int i=0; i < arrow_locations.Count; i++)
{
arrow_locations[i] += 0.05f; //speed of spinning
if( arrow_locations[i] >= 360.0f ) arrow_locations[i] = 0;
//now to get the actual location of the arrow
int which_edge = Mathf.Floor((arrow_locations[i]/360.0f)*outline.Count);
//this will give us a number 0..1 telling us where along the edge the arrow is
float weight_within_edge=(arrow_locations[i] - segment_size*which_edge)/segment_size;
//here we lerp between the two vertices of the edge
Vector3 new_loc = outline[which_edge][0]*(1.0-weight_within_edge) + outline[which_edge][1]*(weight_within_edge);
//now that we have the location of the arrow, draw it
//note, you can get more efficient if using instancing for all arrows
//You can also use line drawing, but i wouldn't recommend that.
DrawMesh(arrow_mesh, new_loc, Quaternion.identity);
}
}
Please note, that when you have the positions of the arrows, you can opt to draw them in 2D in the UI by projecting them onto the camera plane. The lines aside from the arrows are themselves static, so you can draw them as part of the mesh very easily. Also note, I make no mention of the objects position, all values should probably be defined in local space, then transformed with the object. You can transform the drawn stuff in the the DrawMesh function by supplying a a transform matrix.
I think a shader with a parameterized radial mask would be the best way to do this. I have never done one myself, so I only have a general idea of how it's done, but here is how it would work AFAIK:
Create some kind of cell shader that can draw the edges of objects.
Create a filter/mask that has an angle shape extruding radially from the center to the edges; you can control the shape/angle using a parameter. Unity already has something similar to this in the Tanks! tutorial - Tank Health lesson.
Note: The tutorial might even be exactly this idea, but I don't remember with enough details to confirm; I'll update the answer after I take a look again.
The tutorial has the same idea, but it applies it using unity's builtin UI stuff.
Using this mask, only the masked area of the shape's edge will be drawn the screen.
By increasing the angle parameter of the mask over time, you can create the effect of the edge of the object getting revealed radially over time. Which seems to be exactly what you want.
To help visualize, a very professional diagram made in paint:
light blue = mask.
dark blue = "revealed" part of the mask (angle parameter). Plus how it would behave if the angle is increased (arrow).
green = object.
black = outline being drawn to the screen.

Diagonal Shadow with GDI+

I am trying to draw a diagonal shadow.
First I make all pixel to black:
Next with a simple for cicle this is are the result
Now I want to stretch this image diagonally to simulate a shadow.
I have tried:
Bitmap b = new Bitmap(tImage.Width + 100, tImage.Height);
Graphics p = Graphics.FromImage(b);
p.RotateTransform(30f);
p.TranslateTransform(100f, -200f);
p.DrawImage(tImage, new Rectangle(0, -20, b.Width+20, b.Height));
but the images are rotated and translated.
Please anyone have a solution for me?
I need it to look like this (created in Photoshop):
Creating a nice dropshadow is quite a task using Winforms and GDI+.
It features neither polygon scaling nor blurring; and let's not even think about 3D..! - But we can at least do a few things without too much work and get a nice result for many images..
Let's assume you already have an image that is cut out from its background.
The next step would be to turn all colors into black.
Then we most likely would want to add some level of transparency, so that the background the shadow falls on, still shines through.
Both task are done quite effectively by using a suitable ColorMatrix.
With a very transparent version we can also create simple blurring by drawing the image with offsets. For best results I would draw it nine times with 3 differents weights/alpha values..
High quality blurring is an art as you can see by even just looking at the filters and adjustments in pro software like Adobe Photoshop or Affinity Photo. Here is a nice set of interesting links..
But since we are only dealing with a b/w bitmap a simplitstic appraoch is good enough.. I use 3 alpha values of 5%, 10% and 20% for the 4 corner, the 4 edge and the 1 center drawings.
The final step is drawing the shadow with some skewing.
This is explained here; but while this is seemingly very simple it is also somewhat impractical. The three points the DrawImage overlay expects need to be calculated.
So here is a method that does just that; do note that is is a strongly simplified method:
The overlay takes three points, that is 6 floats. We only use 3 numbers:
one for the amount of skewing; 0.5 means the top is shifted to the right by half the width of the bitmap.
the other two are the scaling of the resulting bounding box. 1 and 0.5 mean that the width is unchanged and the height is reduced to 50%.
Here is the function:
public Bitmap SkewBitmap(Bitmap inMap, float skewX, float ratioX, float ratioY )
{
int nWidth = (int)(inMap.Width * (skewX + ratioX));
int nHeight = (int)(Math.Max(inMap.Height, inMap.Height * ratioY));
int yOffset = inMap.Height - nHeight;
Bitmap outMap = new Bitmap(nWidth, nHeight);
Point[] destinationPoints = {
new Point((int)(inMap.Width * skewX), (int)(inMap.Height * ratioY) + yOffset),
new Point((int)(inMap.Width * skewX + inMap.Width * ratioX),
(int)(inMap.Height * ratioY) + yOffset),
new Point(0, inMap.Height + yOffset ) };
using (Graphics g = Graphics.FromImage(outMap))
g.DrawImage(inMap, destinationPoints);
return outMap;
}
Note a few simplifications:
If you want to drop the shadow to the left you will need to not just move the first two points to the left but also to adapt the calculation of the width and also the way you overlay the object over the shadow.
If you study the MSDN example you will see that the DrawImage overlay also allows to do a rotation. I didn't add this to our function, as it is a good deal more complicated to calculate and even to just to write a signature.
If you wonder where the info of the six numbers go, here is the full layout:
3 go into our parameters
1 would be the angle of the rotation we don't do
2 could be either the rotation center point or a point (deltaX&Y) the by which the result is translated
If you look closely you can see the shadow of the left foot is a little below the foot. This is because the feet are not at the same level and with the vertical compression the base lines drift apart. To correct that we would either modify the image or add a tiny rotation after all.
Looking at your example imag it is clear that you will nee to take it apart and treat 'house' and 'tree' separately!
The signature is kept simple; this always a balance between ease of use and effort in coding. On could wish for a paramter the takes angle to control the skewing. Feel free to work out the necessary calculations..
Note that adding the functions behind the other buttons would go beyond the scope of the question. Suffice it to say that most are just one line to do the drawing and a dozen or so to set up the colormatrix..
Here is the code in the 'Skew' button:
Bitmap bmp = SkewBitmap((Bitmap)pictureBox4.Image, 0.5f, 1f, 0.5f);
pictureBox5.Image = pictureBox1.Image;
pictureBox5.BackgroundImage = bmp;
pictureBox5.ClientSize = new Size(bmp.Width, bmp.Height);
Instead of drawing the object over the shadow I make use of the extra layer of the PictureBox. You would of course combine the two Bitmaps..

3D z-buffer c# GDI plus

Im writting very simple 3d engine in c# and GDI+, just for render some models (I think Directx or OpenGL is like shovel to eat soup). So far I have succesfully implemented drawing Wireframe of my model, but next step is of course Faces. And there is my problem, for now I just project my 3d points to 2d point and then drawn it using simple
for each faceg.DrawPolygon(Pens.Red, projected_points); and for wireframe its ok.
It is possible to calculate overlapping part of polygon? and then draw FilledPolygon,
Or better idea is drawing pixel by pixel and if z-buffer of my pixel is further then set new pixel.
If first option is possible, which one is faster (for implement and calculating)?
It is possible to calculate overlapping part of polygon? and then draw FilledPolygon, Or
better idea is drawing pixel by pixel and if z-buffer of my pixel is further then set
new pixel.
If first option is possible, which one is faster (for implement and calculating)?
Yes, it is possible. You can test every polygon with every other of your list. The complexity depends on the type of the polygon (of course, it's easiest with triangles). But the performance may drop drastically with high count of polygons. And even if you find the overlapping areas, you will need to interpolate colors, or texture coordinates (if you plan to use such). Also I'm not sure about the API you use for drawing, but GDI doesn't support fill polygon with interpolated colors.
I have heard that this was the approach used in 3d graphics before inventing the Z buffer. :)
I once tried to realize similar project and used Z-buffer + my own routine to fill triangles with interpolated colors (which uses the Z-buffer). I drawed directly to a GDI bitmap's pixel data buffer. Then after all polygons has been rendered, I bitblt'ed the result to the screen.

Precise pixel movement in Canvas

I am doing some sort of drawing software in WPF, and I have certain visual elements in a Canvas like for example Rectangles and Lines. I have implemented dragging of those elements around the Canvas to move them. The motion must be aligned to pixels, I read WPF uses points and not pixels so it has become a concern of mine to know whether my lines or rectangles are aligned to pixels. I tried using SnapsToPixels, but I'm not sure it will do the trick, or if it will do it when I'm moving the visuals around.
Finally, I must implement moving visuals with the keyboard, a single cursor stroke means move the visual exactly one pixel, how can I do this from the code behind? I assume doing something like:
Canvas.SetLeft(visual) = Canvas.GetLeft(visual) + 1;
Will only add one point to its position, and not one pixel, how can I move exactly one pixel in the Canvas?
Thank you very much.
It might help to use SnapToDevicePixels for your canvas.
Is this what you are looking for?
Matrix m =
PresentationSource.FromVisual(Application.Current.MainWindow)
.CompositionTarget.TransformToDevice;
double pixelSizeX = m.M11;
double pixelSizeY = m.M22;

Matrix Multiplication To Rotate An Image In C#

I need to write a program that uses matrix multiplication to rotate an image (a simple square), based on the center of the square, a certain amount of degree based on what I need. Any help on this would be greatly appreciated. I almost have no clue as to what I'm doing because I have not taken so much as a glance at Calculus.
Take a look at http://www.aforgenet.com/framework/. This is a complete image processing framework in C# that I'm using on a project. I just checked their help and they have a function that does what you want -
// create filter - rotate for 30 degrees keeping original image size
RotateBicubic filter = new RotateBicubic( 30, true );
// apply the filter
Bitmap newImage = filter.Apply( image );
It is an LGPL library, so if licensing is an issue, if you link against their binaries, you will have no issues. Their are also other libraries out there.
If you do decide to write it yourself, be careful about speed as C# doing number crunching is not great. But there are ways to work around it.
Here's a good code project article discussing just what you're wanting:
http://www.codeproject.com/KB/GDI-plus/matrix_transformation.aspx
Rotating an digital image in the plane boils down to a lot of 2X2 matrix multiplications. There's no calculus involved here! You don't need an entire image processing framework to rotate a square image - unless this is really performance sensitive in terms of image quality and speed.
Go and read the first half of Wikipedia's article on the rotation matrix and that should get you off to a good start.
In a nutshell, establish your origin (perhaps the center of the image if that's where you want to rotate around), then compute in pixel space the coordinate of a pixel you'd like to rotate, and multiply by your rotation matrix (see article.). Once you've done the multiply, you'll have your new coordinates of the pixel in pixel space. Write out that pixel in another image buffer and you'll be off and rotating. Repeat. Note that once you know your angle of rotation, you only need compute your rotation matrix once!
Have fun,
Paul

Categories