Draw arrow between on line between two points - c#

how can i draw an arror to show the direction of line ? i manage to do but the arrow not in the right shape.
//For Line
Point point1 = new Point(100, 110);
Point point2 = new Point(300, 210);
Point point3 = new Point(200, 310);
Point point4 = new Point(100,310);
e.Graphics.DrawLines(pen, points);
//For Arrow
e.Graphics.DrawLine(pen, 200, 150, 180, 130);
e.Graphics.DrawLine(pen, 200, 150, 180, 150);

Another example:
Produced by:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Point[] points = {
new Point(100, 110),
new Point(300, 210),
new Point(200, 310),
new Point(100, 310)
};
for(int i=0; i<(points.Length-1); i++)
{
Point p1 = points[i];
Point p2 = points[i + 1];
e.Graphics.DrawLine(Pens.Black, p1, p2);
float angle = getAngle(p1, p2);
Point mid = getMidPoint(p1, p2);
e.Graphics.TranslateTransform(mid.X, mid.Y);
e.Graphics.RotateTransform(angle);
e.Graphics.RotateTransform(135);
e.Graphics.DrawLine(Pens.Black, new Point(0, 0), new Point(8, 0));
e.Graphics.RotateTransform(-270);
e.Graphics.DrawLine(Pens.Black, new Point(0, 0), new Point(8, 0));
e.Graphics.ResetTransform();
}
}
private float getAngle(Point p1, Point p2)
{
float deltaX = p2.X - p1.X;
float deltaY = p2.Y - p1.Y;
return (float)(Math.Atan2(deltaY, deltaX) * 180.0 / Math.PI);
}
private Point getMidPoint(Point p1, Point p2)
{
return new Point((p1.X + p2.X)/2,(p1.Y+p2.Y)/2);
}

I think you want something like this:
and here is the code to do it:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.pictureBox1.Paint += PictureBox1_Paint;
}
private void PictureBox1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
for (int i = 0; i < 5; i++)
{
DrawLineWithArrow(e.Graphics,
Color.Blue,
new PointF(50, 50),
new PointF(340, 120+35*i),
4f+3f*i, false);
DrawLineWithArrow(e.Graphics,
Color.Red,
new PointF(340, 120+35*i),
new PointF(340+290, 50),
4f+3f*i, true);
}
}
public void DrawLineWithArrow(Graphics g, Color color, PointF start, PointF end, float arrowSize=8f, bool filled = false)
{
if (start==end) return;
PointF mid = new PointF((start.X+end.X)/2, (start.Y+end.Y)/2);
float angle = (float)(180/Math.PI*Math.Atan2(end.Y-start.Y, end.X-start.X));
var gp = new GraphicsPath();
gp.AddLines(
new PointF[]
{
new PointF(-arrowSize, -arrowSize/3),
new PointF(0, 0),
new PointF(-arrowSize, arrowSize/3)
}
);
if (filled)
{
gp.CloseFigure();
}
var state = g.Save();
using (Pen pen = new Pen(color, 0))
{
g.DrawLine(pen, start, end);
g.TranslateTransform(
mid.X,
mid.Y);
g.RotateTransform(angle);
if (filled)
{
using (Brush fill = new SolidBrush(color))
{
g.FillPath(fill, gp);
}
}
g.DrawPath(pen, gp);
}
g.Restore(state);
}
}
I took advantage of Graphics.TranslateTransform() and Graphics.RotateTransform() to move and align the coordinate system in the middle of the line and along the line. The drawing of the arrow is much simpler than trying to do vector rotations by hand.

Related

Using Matrix.Rotate more than once C# Winforms

I've been trying to solve a problem I'm having with rotating an oval. The code that I'm posting works, but it's mimicking the kind of code I have to work with for real. Meaning, I can't use the OnPaint override and I'm limited to what I can do in the main code. I'm adding an oval to a graphic layer, and I need to be able to rotate, move and resize the oval. Move and resizing work flawlessly, but rotating doesn't work as I need it to.
If you click in the small box at the 9 oclock position,
the oval will rotate as expected:
The required behavior is to be able to click in the small box at the 12 oclock position, and have the oval rotate again. This does not occur. In order to get the oval to rotate again you need to click in the original 9 oclock position. What I'm really, really trying to find out is how to get the coordinates of the box at the 12 oclock position (or what ever position or location that box ends up after rotating) so that I can rotate it again. Thus far, I have been unable to figure it out. Please try and understand, I'm working with old code that was poorly written and I'm not allowed to change very much of it. What I write must integrate with what's already there. Below is the code snippet that demonstrates what I'm doing. I know I'm missing something obvious, just don't know what. Thanks.
public partial class Form1 : Form
{
int theAngle = 0;
Pen pen2 = new Pen(Color.FromArgb(255, 68, 125, 255), 4);
Pen pen3 = new Pen(Color.Green, 4);
Pen smallPen = new Pen(Color.Black, 1);
PointF center = new PointF(0, 0);
Rectangle rectangle = new Rectangle(20, 20, 100, 30);
Rectangle myRect2 = new Rectangle();
bool mouseBtnDown = false;
Graphics gw;
public Form1()
{
InitializeComponent();
this.MouseDown += mouseDown;
gw = this.CreateGraphics();
}
private void mouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (myRect2.Contains(e.Location))
theAngle+=90;
rotate();
}
if (e.Button == MouseButtons.Right)
{
//oval = false;
//mouseBtnDown = false;
theAngle = 0;
rectangle.X = e.X - 50;
rectangle.Y = e.Y - 15;
rectangle.Width = 100;
rectangle.Height = 30;
center.X = rectangle.Left + (0.5f * rectangle.Width);
center.Y = rectangle.Top + (0.5f * rectangle.Height);
myRect2.Size = new Size(15, 15);
myRect2.Location = new Point(rectangle.Left - 15, (rectangle.Top - (rectangle.Height / 2)) + 15);
drawstuff();
// Invalidate();
}
}
public void rotate()
{
var matrix = new Matrix();
matrix.RotateAt(theAngle, center);
gw.Transform = matrix;
drawstuff();
}
public void drawstuff()
{
gw.SmoothingMode = SmoothingMode.AntiAlias; // Creates smooth lines.
gw.DrawEllipse(pen2, rectangle);
gw.DrawRectangle(smallPen, myRect2);
}
}
You can use the Transform matrix to rotate points. So what I've done is get the 4 corner points of myRect2, rotate them using the same Transform matrix, then assign these to a rectangle. You can then use this new rectangle to check the location. I also changed the call to drawstuff() at the end of the right button click to call rotate(), this way the rotated rectangle can get updated when the ellipse is first placed, and the graphics transform angle gets updated to 0.
public partial class Form1 : Form
{
int theAngle = 0;
Pen pen2 = new Pen(Color.FromArgb(255, 68, 125, 255), 4);
Pen pen3 = new Pen(Color.Green, 4);
Pen smallPen = new Pen(Color.Black, 1);
PointF center = new PointF(0, 0);
Rectangle rectangle = new Rectangle(20, 20, 100, 30);
Rectangle myRect2 = new Rectangle();
Rectangle rotatedRect2 = new Rectangle();
bool mouseBtnDown = false;
Graphics gw;
public Form1()
{
InitializeComponent();
this.MouseDown += mouseDown;
gw = this.CreateGraphics();
}
private void mouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (rotatedRect2.Contains(e.Location))
theAngle += 90;
rotate();
}
if (e.Button == MouseButtons.Right)
{
//oval = false;
//mouseBtnDown = false;
theAngle = 0;
rectangle.X = e.X - 50;
rectangle.Y = e.Y - 15;
rectangle.Width = 100;
rectangle.Height = 30;
center.X = rectangle.Left + (0.5f * rectangle.Width);
center.Y = rectangle.Top + (0.5f * rectangle.Height);
myRect2.Size = new Size(15, 15);
myRect2.Location = new Point(rectangle.Left - 15, (rectangle.Top - (rectangle.Height / 2)) + 15);
rotate();
//drawstuff();
// Invalidate();
}
}
public void rotate()
{
var matrix = new Matrix();
matrix.RotateAt(theAngle, center);
gw.Transform = matrix;
// Get the 4 corner points of myRect2.
Point p1 = new Point(myRect2.X, myRect2.Y),
p2 = new Point(myRect2.X + myRect2.Width, myRect2.Y),
p3 = new Point(myRect2.X, myRect2.Y + myRect2.Height),
p4 = new Point(myRect2.X + myRect2.Width, myRect2.Y + myRect2.Height);
Point[] pts = new Point[] { p1, p2, p3, p4 };
// Rotate the 4 points.
gw.Transform.TransformPoints(pts);
// Update rotatedRect2 with those rotated points.
rotatedRect2.X = pts.Min(pt => pt.X);
rotatedRect2.Y = pts.Min(pt => pt.Y);
rotatedRect2.Width = pts.Max(pt => pt.X) - pts.Min(pt => pt.X);
rotatedRect2.Height = pts.Max(pt => pt.Y) - pts.Min(pt => pt.Y);
drawstuff();
}
public void drawstuff()
{
gw.SmoothingMode = SmoothingMode.AntiAlias; // Creates smooth lines.
gw.DrawEllipse(pen2, rectangle);
gw.DrawRectangle(smallPen, myRect2);
}
}
Something to note. Drawing to the screen like this (using the form's created graphics and drawing using your own draw function) means the ellipses/rectangles are only drawn once. i.e. if you draw a few then minimize your form, when you bring it back up the ellipses will be gone. Not sure if this is what you're after or not. One way to fix this would be to draw the ellipses to a Bitmap and then in the form's Paint event this bitmap is draw to the form.

How do I rotate an Image and Scale it up using only one method?

Here's what I do to Rotate and Scale. But so far, if the rotation is working, the scaling isn't and vice versa. So how do I combine rotation and scaling in one method? I feels like they can't coexist using my code.
....................................................................................................................................................................
Here's what I have for now:
Image Drawing:
public LayerClass ImageDrawing(LayerClass.Type img, Bitmap bm, Rectangle imgRect, String filepath, int angle, PaintEventArgs e)
{
bm = ImageClass.GrayscaleImage(bm);
bm = MakeTransparentImage(bm);
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
bm = RotateImage(bm, angle, imgRect);
imgRect = new Rectangle((int)(Shape.center.X - (bm.Width / 2)), (int)(Shape.center.Y - (bm.Height / 2)), (int)bm.Width, (int)bm.Height);
e.Graphics.DrawImage(bm, imgRect);
this.imageBitmap = bm;
this.filePath = filePath;
this.rotationAngle = angle;
this.location = location;
this.imageRect = imgRect;
return new LayerClass(LayerClass.Type.Image, this, filePath, imgRect);
}
Rotation:
public static Bitmap RotateImage(Bitmap bitmap, float angle, Rectangle rect)
{
Matrix matrix = new Matrix();
matrix.Translate(bitmap.Width / -2, bitmap.Height / -2, MatrixOrder.Append);
matrix.RotateAt(angle, new System.Drawing.Point(0, 0), MatrixOrder.Append);
using (GraphicsPath graphicsPath = new GraphicsPath())
{
graphicsPath.AddPolygon(new System.Drawing.Point[] { new System.Drawing.Point(0, 0), new System.Drawing.Point(bitmap.Width, 0), new System.Drawing.Point(0, bitmap.Height) });
graphicsPath.Transform(matrix);
System.Drawing.PointF[] points = graphicsPath.PathPoints;
rect = boundingBox(bitmap, matrix);
Bitmap resultBitmap = new Bitmap(rect.Width, rect.Height);
using (Graphics g = Graphics.FromImage(resultBitmap))
{
Matrix matrix2 = new Matrix();
matrix2.Translate(resultBitmap.Width / 2, resultBitmap.Height / 2, MatrixOrder.Append);
g.Transform = matrix2;
g.DrawImage(bitmap, points);
return resultBitmap;
}
}
}
Scaling:
private void trackBar_ScaleImg_Scroll(object sender, EventArgs e)
{
if(rb_BothImage.Checked)
{
if (imgRect.Width > imgRect.Height)
{
imgRect.Width = trackBar_ScaleImg.Value;
imgRect.Height = (int)(trackBar_ScaleImg.Value / aspect);
ImageBitmap = new Bitmap(ImageBitmap, new Size(imgRect.Width, imgRect.Height));
}
else if (imgRect.Height > imgRect.Width)
{
imgRect.Height = trackBar_ScaleImg.Value; //64mm
imgRect.Width = (int)(trackBar_ScaleImg.Value / aspect);
ImageBitmap = new Bitmap(ImageBitmap, new Size(imgRect.Width, imgRect.Height));
}
else if (imgRect.Width == imgRect.Height)
{
imgRect.Width = trackBar_ScaleImg.Value;
imgRect.Height = trackBar_ScaleImg.Value;
}
imgRect.X = (int)(Shape.center.X - (imgRect.Width / 2));
imgRect.Y = (int)(Shape.center.Y - (imgRect.Height / 2));
ImageBitmap = new Bitmap(ImageBitmap, new Size(imgRect.Width, imgRect.Height));
}
pictureBox_Canvass.Invalidate();
}
You can add another matrix transformation for scaling: matrix.Scale(2, 2, MatrixOrder.Append);
Matrix matrix = new Matrix();
matrix.Translate(bitmap.Width / -2, bitmap.Height / -2, MatrixOrder.Append);
matrix.RotateAt(angle, new System.Drawing.Point(0, 0), MatrixOrder.Append);
matrix.Scale(2, 2, MatrixOrder.Append);
using (GraphicsPath graphicsPath = new GraphicsPath())

How can I add textbox control's behaviors into my custom control?

I have a custom rounded textbox. But I couldn't add the textbox behaviors like text editing, text selection etc. Those properties take much time if I decide make myself. How can I add this properties into my textbox?
My TextBox class:
public class AltoTextBox : Control
{
public AltoTextBox()
{
SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.SupportsTransparentBackColor |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.UserPaint, true);
BackColor = Color.Transparent;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
RoundedRectangleF strokeRect = new RoundedRectangleF(Width, Height, 10);
RoundedRectangleF innerRect = new RoundedRectangleF(Width - 0.5f, Height - 0.5f, 10f, 0.5f, 0.5f);
e.Graphics.DrawPath(Pens.Black, strokeRect.Path);
e.Graphics.FillPath(Brushes.White, innerRect.Path);
}
}
public class RoundedRectangleF
{
Point location;
float radius;
GraphicsPath grPath;
float x, y;
float width, height;
public RoundedRectangleF(float width, float height, float radius,float x = 0,float y = 0)
{
location = new Point(0, 0);
this.radius = radius;
RectangleF upperLeftRect = new RectangleF(x, y, 2 * radius, 2 * radius);
RectangleF upperRightRect = new RectangleF(width - 2 * radius - 1, x, 2 * radius, 2 * radius);
RectangleF lowerLeftRect = new RectangleF(x, height - 2 * radius - 1, 2 * radius, 2 * radius);
RectangleF lowerRightRect = new RectangleF(width - 2 * radius - 1, height - 2 * radius - 1, 2 * radius, 2 * radius);
grPath = new GraphicsPath();
grPath.AddArc(upperLeftRect, 180, 90);
grPath.AddArc(upperRightRect, 270, 90);
grPath.AddArc(lowerRightRect, 0, 90);
grPath.AddArc(lowerLeftRect, 90, 90);
grPath.CloseAllFigures();
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public RoundedRectangleF()
{
}
public GraphicsPath Path
{
get
{
return grPath;
}
}
public RectangleF Rect
{
get
{
return new RectangleF(x, y, width, height);
}
}
public float Radius
{
get
{
return radius;
}
set
{
radius = value;
}
}
}
I have found a solution from Hazeldev's custom controls.
In this solution we add a textbox control as our child control.
public class AltoTextBox : Control
{
int radius = 15;
public TextBox box = new TextBox();
GraphicsPath Shape;
public AltoTextBox()
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.ResizeRedraw, true);
AddTextBox();
Controls.Add(box);
BackColor = Color.Transparent;
ForeColor = Color.DimGray;
Text = null;
Font = new Font("Comic Sans MS", 11);
Size = new Size(135, 33);
DoubleBuffered = true;
}
void AddTextBox()
{
box.Size = new Size(Width - 2*radius, Height - 6);
box.Location = new Point(radius, 3);
box.BorderStyle = BorderStyle.None;
box.TextAlign = HorizontalAlignment.Left;
box.Multiline = true;
box.Font = Font;
}
protected override void OnBackColorChanged(EventArgs e)
{
base.OnBackColorChanged(e);
}
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
box.Text = Text;
}
GraphicsPath innerRect;
protected override void OnFontChanged(EventArgs e)
{
base.OnFontChanged(e);
box.Font = Font;
}
protected override void OnResize(System.EventArgs e)
{
base.OnResize(e);
Shape = new RoundedRectangleF(Width, Height, radius).Path;
innerRect = new RoundedRectangleF(Width - 0.5f, Height - 0.5f, radius, 0.5f, 0.5f).Path;
AddTextBox();
}
protected override void OnPaint(PaintEventArgs e)
{
Bitmap bmp = new Bitmap(Width, Height);
Graphics grp = Graphics.FromImage(bmp);
grp.SmoothingMode = SmoothingMode.HighQuality;
grp.DrawPath(Pens.Gray, Shape);
grp.FillPath(Brushes.White, innerRect);
e.Graphics.DrawImage((Image)bmp.Clone(), 0, 0);
base.OnPaint(e);
}
}

Label a polygon

I have a function that I use to createan array of points, so I can draw a polygon, I want to label inside of this polygons, I know it can be done using drawstring or label control, but I want to make sure I have the same orientation of the polygon in my case they are rectangles also control the font size depend on the shape size.
I tried to create a rect inside the Draw string didn't work, any Ideas
private void BuildImage()
{
Graphics refGraph = this.CreateGraphics();
IntPtr hdc = refGraph.GetHdc();
Metafile image = new Metafile(hdc, EmfType.EmfOnly, "Shapes");
using (var g = Graphics.FromImage(image))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
SolidBrush myBrush = new SolidBrush(Color.Black);
Pen p = new Pen(Color.Red, 0.2f);
foreach (CircuitData.ResistorRow resistorRow in ResistorData.Resistor)
{
RectangleF rec = new RectangleF((float)(resistorRow.CenterX - resistorRow.Length / 2), (float)(resistorRow.CenterY - resistorRow.Width / 2), (float)resistorRow.Length, (float)resistorRow.Width);
float orientation = 360 - (float)resistorRow.Orientation;
PointF center = new PointF((float)resistorRow.CenterX, (float)resistorRow.CenterY);
PointF[] points = CreatePolygon(rec, center, orientation);
if (!Double.IsNaN(resistorRow.HiX) && !Double.IsNaN(resistorRow.HiY))
{
g.FillEllipse(myBrush, (float)resistorRow.HiX - 0.5f, (float)resistorRow.HiY - 0.5f, 1, 1);
g.DrawLine(p, new PointF((float)resistorRow.HiX, (float)resistorRow.HiY), center);
}
g.FillPolygon(myBrush, points);
Font drawFont = new Font("cursor", 1);
SolidBrush textBrush = new SolidBrush(Color.Blue);
//g.Transform = matrix;
g.DrawString(resistorRow.ComponentName, drawFont, textBrush, points[0]);
}
}
refGraph.ReleaseHdc(hdc);
refGraph.Dispose();
Image = image;
}
private PointF[] CreatePolygon(RectangleF rec, PointF center, float orientation)
{
PointF TL = new PointF(rec.Left, rec.Top);
PointF TR = new PointF(rec.Right, rec.Top);
PointF BL = new PointF(rec.Left, rec.Bottom);
PointF BR = new PointF(rec.Right, rec.Bottom);
PointF[] points = new PointF[] { BL, TL, TR, BR, BL };
matrix = new System.Drawing.Drawing2D.Matrix();
matrix.RotateAt(orientation, center);
matrix.TransformPoints(points);
return points;
}
Apply your rotation matrix to the graphic context you're working with:
e.Graphics.Transform = matrix;
e.Graphics.FillPolygon(textBrush, points);
e.Graphics.DrawString(resistorRow.ComponentName, drawFont, textBrush2, TL);
EDIT: Some sample code:
public class ResistorWithLabel
{
public string ComponentName { get; set; }
public RectangleF Rect { get; set; }
public float Orientation { get; set; }
public Color BackgroundColor { get; set; }
public Color ForegroundColor { get; set; }
public int FontSize { get; set; }
public void Draw(Graphics g)
{
Matrix contextMatrix = g.Transform;
Matrix matrix = new Matrix();
matrix.RotateAt(Orientation, new PointF((Rect.Left+Rect.Right)/2, (Rect.Top+Rect.Bottom)/2));
SolidBrush polygonBrush = new SolidBrush(BackgroundColor);
SolidBrush textBrush = new SolidBrush(ForegroundColor);
Font font = new Font("Courier", FontSize);
PointF TL = new PointF(Rect.Left, Rect.Top);
PointF TR = new PointF(Rect.Right, Rect.Top);
PointF BL = new PointF(Rect.Left, Rect.Bottom);
PointF BR = new PointF(Rect.Right, Rect.Bottom);
PointF[] points = new PointF[] { BL, TL, TR, BR };
g.Transform = matrix;
g.FillPolygon(polygonBrush, points);
g.DrawString(ComponentName, font, textBrush, TL);
g.Transform = contextMatrix;
}
}
private void Form3_Paint(object sender, PaintEventArgs e)
{
ResistorWithLabel r1 = new ResistorWithLabel();
r1.ComponentName = "Resistor 1";
r1.Rect = new RectangleF(50, 100, 100, 50);
r1.Orientation = 25;
r1.BackgroundColor = Color.Blue;
r1.ForegroundColor = Color.Yellow;
r1.FontSize = 16;
r1.Draw(e.Graphics);
ResistorWithLabel r2 = new ResistorWithLabel();
r2.ComponentName = "Resistor 2";
r2.Rect = new RectangleF(200, 100, 200, 100);
r2.Orientation = 75;
r2.BackgroundColor = Color.Gray;
r2.ForegroundColor = Color.Orange;
r2.FontSize = 32;
r2.Draw(e.Graphics);
}

Refreshing picturebox stops other controls that need to redraw

So I have this steering wheel control, and when I rotate it with the mouse and refresh the image it stops my other panel control from drawing its graph from updating/redrawing. Below is the code for rotating and redrawing the steering wheel.
private readonly Bitmap _originalHelmImage;
private Bitmap _newHelmImage;
private void HelmPb_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
PictureBox p = (PictureBox) sender;
Bitmap bmp = (Bitmap) p.Image;
//GetPixel works on initial image, not stretched one.
double ratio = (double) p.Image.Width/p.Width;
//Ignore the non-helm portion of the helm.
Color trans = bmp.GetPixel(Convert.ToInt32(ratio*e.X), Convert.ToInt32(ratio*e.Y));
if (trans.A.Equals(0))
{
_dontTurn = true;
return;
}
_offsetAngle = OffsetAngle() - _lastAngleTurn;
_lastAngleTurn = 0;
_dontTurn = false;
}
private double OffsetAngle()
{
int helmXMid = HelmPb.PointToScreen(Point.Empty).X + (HelmPb.Width / 2);
int helmYMid = HelmPb.PointToScreen(Point.Empty).Y + (HelmPb.Height / 2);
double angle = AngleFromPoints(MousePosition, new Point(helmXMid, helmYMid));
return angle;
}
private void HelmPb_MouseMove(object sender, MouseEventArgs e)
{
if ((e.Button != MouseButtons.Left) || _dontTurn) return;
double angle = OffsetAngle();
float degrees = Convert.ToSingle(angle - _offsetAngle);
//float diff = ((360 - degrees) - _deltaHelmTurn%360)%360;
//float diff = (_lastAngleTurn - (degrees - 360)) % 360;
double diff = 90 - angle;
_deltaHelmTurn += Convert.ToSingle(diff - _lastAngleTurn);
if (Math.Abs(_deltaHelmTurn) >= (_maxHelmTurn*360.0))
{
_deltaHelmTurn = Convert.ToSingle(_maxHelmTurn*360.0);
degrees = 0;
}
_lastAngleTurn = Convert.ToSingle(degrees);
_newHelmImage = RotateImage(_originalHelmImage, -degrees);
HelmPb.Image.Dispose();
HelmPb.Image = _newHelmImage;
WaterDepthPlot.Invalidate();
HelmPb.Refresh();
}
double AngleFromPoints(Point pt1, Point pt2)
{
Point p = new Point(pt1.X - pt2.X, pt1.Y - pt2.Y);
double alpha;
if (p.Y == 0) alpha = p.X > 0 ? 0d : 180d;
else
{
double f = 1d * p.X / (Math.Sqrt(p.X * p.X + p.Y * p.Y));
alpha = Math.Acos(f) * 180d / Math.PI;
if (p.Y > 0) alpha = 360d - alpha;
}
return alpha;
}
private Bitmap RotateImage(Bitmap b, float angle)
{
//Create a new empty bitmap to hold rotated image.
Bitmap returnBitmap = new Bitmap(b.Width, b.Height);
//Make a graphics object from the empty bitmap.
Graphics g = Graphics.FromImage(returnBitmap);
//move rotation point to center of image.
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.TranslateTransform(b.Width/2F, b.Height/2F);
//Rotate.
g.RotateTransform(angle);
//Move image back.
g.TranslateTransform(-b.Width/2F, -b.Height/2F);
//Draw passed in image onto graphics object.
g.DrawImage(b, new PointF(0.0F, 0.0F));
return returnBitmap;
}
Below is the code for updating my graph. It is never ran when the steering wheel is being moved. Once the users stops moving, it will update. Is there a way for it to constantly update along with it? I tried throwing a refresh/invalidate of the panel into the mousemove event so whenever the wheel is refreshed, so is the graph; no luck. Any suggestions?
private void WaterDepthPlot_Paint(object sender, PaintEventArgs e)
{
Pen pen = new Pen(Color.FromArgb(70, 75, 80));
int xOffset = WaterDepthPlot.Location.X;
e.Graphics.DrawLine(pen, new Point(0, 0), new Point(WaterDepthPlot.Width, 0));
e.Graphics.DrawLine(pen, new Point(0, (WaterDepthPlot.Height/5)),
new Point(WaterDepthPlot.Width, (WaterDepthPlot.Height/5)));
e.Graphics.DrawLine(pen, new Point(0, (2*WaterDepthPlot.Height/5)),
new Point(WaterDepthPlot.Width, (2*WaterDepthPlot.Height/5)));
e.Graphics.DrawLine(pen, new Point(0, (3*WaterDepthPlot.Height/5)),
new Point(WaterDepthPlot.Width, (3*WaterDepthPlot.Height/5)));
e.Graphics.DrawLine(pen, new Point(0, (4*WaterDepthPlot.Height/5)),
new Point(WaterDepthPlot.Width, (4*WaterDepthPlot.Height/5)));
e.Graphics.DrawLine(pen, new Point((ThirdXScaleUnit.Location.X - xOffset), 0),
new Point((ThirdXScaleUnit.Location.X - xOffset),
(WaterDepthPlot.Height + WaterDepthPlot.Location.Y)));
e.Graphics.DrawLine(pen, new Point((SecondXScaleUnit.Location.X - xOffset), 0),
new Point((SecondXScaleUnit.Location.X - xOffset),
(WaterDepthPlot.Height + WaterDepthPlot.Location.Y)));
e.Graphics.DrawLine(pen, new Point((FirstXScaleUnit.Location.X - xOffset), 0),
new Point((FirstXScaleUnit.Location.X - xOffset),
(WaterDepthPlot.Height + WaterDepthPlot.Location.Y)));
pen = new Pen(Color.Firebrick);
pen.DashStyle = DashStyle.Dash;
float[] dash = {3, 3};
pen.DashPattern = dash;
double diff = (double) WaterDepthPlot.Height/(5*_depthYScale);
int alertDiff = (int)(_alertDepth * diff);
e.Graphics.DrawLine(pen, new Point(0, alertDiff), new Point(WaterDepthPlot.Width, alertDiff));
pen = new Pen(Color.White);
GraphicsPath gp = new GraphicsPath();
if (_depthCurve.Count < 2) return;
gp.AddCurve(_depthCurve.ToArray());
e.Graphics.DrawPath(pen, gp);
}

Categories