I'm trying to add a dashline for a graph but it keeps coming out as a solid line. How can I fix that?
static public NPlot.Bitmap.PlotSurface2D getDashlineGraph(int itemID, int width, int height)
{
NPlot.Bitmap.PlotSurface2D plot = new NPlot.Bitmap.PlotSurface2D(width, height);
plot.BackColor = Color.WhiteSmoke;
plot.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
LinePlot TotaldashLine = new LinePlot(straightline, timer);
float[] pattern = { 5.0f, 10.0f };
TotaldashLine.Pen = new Pen(Color.Green,0.5f);
TotaldashLine.Pen.DashPattern = pattern;
plot.Add(TotaldashLine, NPlot.PlotSurface2D.XAxisPosition.Bottom, NPlot.PlotSurface2D.YAxisPosition.Right, 100);
Grid oGrid = new Grid();
oGrid.HorizontalGridType = Grid.GridType.Coarse;
oGrid.VerticalGridType = Grid.GridType.Coarse;
plot.Add(oGrid);
plot.Refresh();
return plot;
}
You need to specify that you want your Pen to draw dashed using Pen.DashStyle:
TotaldashLine.Pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
Once you have done that, you can additionally customize the lengths of dashes and gaps using the Pen.DashPattern as you have.
Related
I am using Alturos.YOLO with Emgu CV 3.2 (World.dll) in a C# WPF Application. I am testing this app on an 8GB RAM. But, it is VERY slow. I don't know what seems to be the problem. Here is my code:
private void Timer_Tick(object sender, EventArgs e)
{
var img = capture.QueryFrame();
videoViewer.Source = ToBitmapSource(img);
var memoryStream = new MemoryStream();
img.Bitmap.Save(memoryStream, ImageFormat.Png);
var _items = yolo.Detect(memoryStream.ToArray()).ToList();
var graphics = Graphics.FromImage(img.Bitmap);
var brush = new SolidBrush(Color.LightGreen);
foreach (var item in _items)
{
var x = item.X;
var y = item.Y;
var width = item.Width;
var height = item.Height;
var type = item.Type; // class name of the object
var rect = new Rectangle(x, y, width, height);
var pen = new Pen(Color.LightGreen, 6);
var point = new System.Drawing.Point(x + width / 2, y + height / 2);
graphics.DrawRectangle(pen, rect);
graphics.DrawString($"{item.Type} : {item.Height} * {item.Width}", new Font("Arial", 23f), brush, point);
MessageBox.Show(type);
}
}
You can try one of two things, or both, either reducing the number of classes in your YOLO database to the objects you target only, here is some details, or try to use GPU to accelerate detection using CUDA C++, but you must own a NVidia card. These two methods worked for me and reduced detection time greatly.
My code
Building the column
IconColumn = new DataGridViewImageColumn()
{
Name = "Icon",
HeaderText = "Icon",
SortMode = DataGridViewColumnSortMode.NotSortable,
Width = 50,
ImageLayout = DataGridViewImageCellLayout.Stretch,
Resizable = DataGridViewTriState.False
};
IconColumn.DefaultCellStyle.NullValue = null;
IconColumn.CellTemplate = new ClockDataGridViewIconCell();
Setting an icon
float maxHeight = 200;
float maxWidth = 200;
var r = new Rectangle(0,
0,
(int)Math.Round(maxWidth),
(int)Math.Round(maxHeight)
);
MyClockData.Icon = Utils.ResizeToFitBoundingBox(
new Bitmap(fd.FileName),
r);
The ResizeToFitBoundingBox method
internal static Bitmap ResizeToFitBoundingBox(Image image, in Rectangle box)
{
float maxHeight = box.Width;
float maxWidth = box.Height;
float x = Math.Min(maxWidth / image.Width,
maxHeight / image.Height);
float newW = (float)image.Width * x;
float newH = (float)image.Height * x;
var bmp = new Bitmap((int)Math.Round(maxWidth),
(int)Math.Round(maxHeight));
bmp.MakeTransparent();
using (Graphics gr = Graphics.FromImage(bmp))
{
gr.DrawImage(image, (bmp.Width - newW) / 2,
(bmp.Height - newH) / 2, newW, newH);
}
return bmp;
}
Example icon
I have tried all the 4 possible values for DataGridViewImageColumn.ImageLayout and the cell looks the same:
Normal
Not Set
Stretch
Zoom
None of them Works for what I wish. The official documentation is here. I would like the same behaviour as Forms.ImageLayout.Zoom.
Note: I use .NET Framework v4.6.1.
I solved the problem by adding this line:
IconColumn.ImageLayout = DataGridViewImageCellLayout.Zoom;
after each statement which adds or updates an icon in the DataGridView.
It seems that setting this property to the same value as before repaints the icons in the column in the way the value of the property suggests.
I am writing a C# Direct2D application using SharpDX, however I can understand answers/examples that are provided in C++.
I want to render text and change the width of certain characters to look like the picture:
The letter B expanded to 200% and the letter D is reduced to 50%
In the code below I draw the geometry of the glyphs
And so it is possible to change the width of geometry
But that's not a good solution, because a geometry drawing comes out as blurred as you see in the picture.
In conclusion, there are two questions:
How I change the width of the characters?
How to draw geometries of letters without blurring. (it is possible to render geometry with ClearType?)
private void RenderGlyphRun1(FontFace1 fontFace)
{
var Offsets = new List<GlyphOffset>();
var fontEmSize_ = 12;
GlyphRun glyphRun = new GlyphRun();
glyphRun.FontFace = fontFace;
glyphRun.FontSize = fontEmSize_;
glyphRun.BidiLevel = 1;
var left = 650f;
var top = 50f;
var baseLine = (float)(fontFace.Metrics.LineGap + fontFace.Metrics.Ascent) /
fontFace.Metrics.DesignUnitsPerEm * glyphRun.FontSize;
string textToDraw = "ABCDE";
foreach (char letter in textToDraw)
{
Offsets.Add(new GlyphOffset());
}
var charArr = textToDraw.Select(x => (int)x).ToArray();
glyphRun.Indices = fontFace.GetGlyphIndices(charArr);
var metrics = fontFace.GetDesignGlyphMetrics(glyphRun.Indices, false);
glyphRun.Advances = metrics.Select(x => (float)x.AdvanceWidth /
fontFace.Metrics.DesignUnitsPerEm * glyphRun.FontSize).ToArray();
glyphRun.Offsets = Offsets.ToArray();
RenderTarget2D.BeginDraw();
RenderTarget2D.Clear(SharpDX.Color.White);
RenderTarget2D.DrawGlyphRun(new Vector2(left, top),
glyphRun, new SharpDX.Direct2D1.SolidColorBrush(RenderTarget2D, SharpDX.Color.Black),
MeasuringMode.Natural);
top += baseLine;
var pathGeometry = new PathGeometry(Factory2D);
var geometrySink = pathGeometry.Open();
fontFace.GetGlyphRunOutline(glyphRun.FontSize, glyphRun.Indices,
glyphRun.Advances, glyphRun.Offsets, glyphRun.IsSideways,
glyphRun.BidiLevel % 2 != 0, geometrySink);
geometrySink.Close();
geometrySink.Dispose();
fontFace.Dispose();
var matrix = new Matrix3x2()
{
M11 = 1,
M12 = 0,
M21 = 0,
M22 = 1,
M31 = left,
M32 = top
};
var transformedGeometry = new TransformedGeometry(Factory2D, pathGeometry, matrix);
var brushColor = (Color4)SharpDX.Color.Black;
var brush = new SolidColorBrush(RenderTarget2D, brushColor);
RenderTarget2D.FillGeometry(transformedGeometry, brush);
pathGeometry.Dispose();
transformedGeometry.Dispose();
brush.Dispose();
RenderTarget2D.EndDraw();
}
Since some of the letters should be narrow and some are normal and some are wide, you can not use one GlyphRun, but must create 3 different GlyphRun.
To cause all letters of any GlyphRun to be wide or narrow:
Configure Transform to RenderTarget
Draw the GlyphRun
Return the original Transform
Wide transform: RenderTarget2D.Transform = new SharpDX.Mathematics.Interop.RawMatrix3x2(1.5f, 0, 0, 1, 0, 0);
Narrow transform: RenderTarget2D.Transform = new SharpDX.Mathematics.Interop.RawMatrix3x2(0.5f, 0, 0, 1, 0, 0);
After this solution you do not need to convert GlyphRun to geometry and get mixed up with blurred letters.
Direct2D text rendering functionality is offered in two parts:
1) DrawText and DrawTextLayout method, enables a caller to pass either a string and formatting parameters or a DWrite text layout object for multiple formats. This should be suitable for most callers.
2) The second way is to render text, exposed as the DrawGlyphRun method, provides rasterization for customers who already know the position of the glyphs they want to render. The following two general rules can help improve text performance when drawing in Direct2D.
I now see that you are using the second approach, but in the first one, you can set the rendering to ClearType :
RenderTarget2D.TextAntialiasMode = TextAntialiasMode.Cleartype;
I am not sure how to include it in you example, but the Sharp DX example looks like this:
using System;
using SharpDX;
using SharpDX.Direct2D1;
using SharpDX.DirectWrite;
using SharpDX.Samples;
using TextAntialiasMode = SharpDX.Direct2D1.TextAntialiasMode;
namespace TextRenderingApp
{
public class Program : Direct2D1DemoApp
{
public TextFormat TextFormat { get; private set; }
public TextLayout TextLayout { get; private set; }
protected override void Initialize(DemoConfiguration demoConfiguration)
{
base.Initialize(demoConfiguration);
// Initialize a TextFormat
TextFormat = new TextFormat(FactoryDWrite, "Calibri", 128) {TextAlignment = TextAlignment.Center, ParagraphAlignment = ParagraphAlignment.Center};
RenderTarget2D.TextAntialiasMode = TextAntialiasMode.Cleartype;
// Initialize a TextLayout
TextLayout = new TextLayout(FactoryDWrite, "SharpDX D2D1 - DWrite", TextFormat, demoConfiguration.Width, demoConfiguration.Height);
}
protected override void Draw(DemoTime time)
{
base.Draw(time);
// Draw the TextLayout
RenderTarget2D.DrawTextLayout(new Vector2(0,0), TextLayout, SceneColorBrush, DrawTextOptions.None );
}
[STAThread]
static void Main(string[] args)
{
Program program = new Program();
program.Run(new DemoConfiguration("SharpDX DirectWrite Text Rendering Demo"));
}
}
}
Sample taken from: https://github.com/sharpdx/SharpDX-Samples/blob/master/Desktop/Direct2D1/TextRenderingApp
I have a uniform grid that has rectangles dynamically added to it. I want to remove a particular rectangle, but I am getting the following error when trying to pass it to the Remove method:
Cannot convert from 'System.Drawing.Rectangle' to 'System.Windows.UIElement'
My code is:
Rectangle swatch = (Rectangle)ug_Thumbnails.FindName("s_" + _instance);
ug_Thumbnails.Children.Remove(swatch);
I tried casting, and got an error saying that you couldn't do it.
EDIT: Per request, here's the code to create the rectangle:
System.Windows.Shapes.Rectangle swatch = new System.Windows.Shapes.Rectangle();
swatch.Width = 50;
swatch.Height = 50;
swatch.Margin = new Thickness(0, 5, 5, 0);
swatch.StrokeThickness = 1;
swatch.Stroke = System.Windows.Media.Brushes.Gray;
swatch.Name = "s_" + name.ToString();
double groupsize = 100 / colors.Count();
DrawingBrush blackBrush = new DrawingBrush();
DrawingGroup checkersDrawingGroup = new DrawingGroup();
List<SolidColorBrush> brushes = colors;
double location = 0;
for (int i = 0; i < colors.Count(); i++)
{
GeometryDrawing drawing = new GeometryDrawing(brushes[i], null,
new RectangleGeometry(new Rect(location, 0, groupsize, groupsize)));
checkersDrawingGroup.Children.Add(drawing);
location += groupsize;
}
blackBrush.Drawing = checkersDrawingGroup;
swatch.Fill = blackBrush;
swatch.MouseUp += new MouseButtonEventHandler(loadSwatchResources);
ug_Thumbnails.Children.Add(swatch);
You need to use the Rectangle in System.Windows.Shapes when trying to reference a rectangle in WPF. This is specifically for rectangles in WPF and as such is a bit different than the System.Drawing rectangle class. You should be able to cast to this version of rectangle since it derives from FrameworkElement. See http://msdn.microsoft.com/en-us/library/system.windows.shapes.rectangle(v=vs.110).aspx for more info.
I am creating a C# visual studio forms application that uses zedgraph to chart the data that the program collects but I am running into the following issue when plotting the data:
My y-axis values are usually in the 100,000+ range so when zed graph plots the value it labels the y-axis labels with stuff like 0, 10, 15, 20, 25 and then on the y-axis label it will append "(10^3)" to the title and will plot the values accordingly. What I want to do is have it label the y-axis either with values like 0, 10,000, 15,000, 20,000 etc or 0, 10k, 15k, 20k and so on and not have it adjust the y-axis title.
I tried setting YAxis.Scale.MajorStep = double.Parse("10000"); but the only effect that has is to add a ton of more tick lines on the y-axis but no other effect. Here is my code that graphs the data:
private void createGraph()
{
GraphPane myPane = zdc_graph.GraphPane;
myPane.CurveList.Clear();
myPane.GraphObjList.Clear();
myPane.Title.Text = this.monitoredHost.hostName + "\nWorkState[" +
this.monitoredHost.currentWorkState + "]";
myPane.XAxis.Title.Text = "";
myPane.YAxis.Title.Text = "OPS Per Second";
myPane.YAxis.Scale.FontSpec.FontColor = Color.Blue;
myPane.YAxis.Title.FontSpec.FontColor = Color.Blue;
myPane.YAxis.Scale.MaxAuto = true;
myPane.Y2Axis.Title.Text = "Reading";
myPane.Y2Axis.IsVisible = true;
myPane.Y2Axis.Scale.FontSpec.FontColor = Color.Red;
myPane.Y2Axis.Title.FontSpec.FontColor = Color.Red;
myPane.XAxis.Type = AxisType.Date;
myPane.XAxis.Scale.Format = "T";
myPane.XAxis.Scale.MajorUnit = DateUnit.Second;
myPane.YAxis.Scale.Min = 0;
myPane.YAxis.Scale.MajorStep = double.Parse("10000");
myPane.Y2Axis.Scale.Min = 0;
LineItem kpiCurve = myPane.AddCurve("OPS Per Second",
this.monitoredHost.graphKpiList,
Color.Blue,SymbolType.Circle);
LineItem pwrCurve = myPane.AddCurve("Reading",
this.monitoredHost.graphPwrList, Color.Red,
SymbolType.Circle);
kpiCurve.Line.Width = 2.0F;
kpiCurve.Symbol.Size = 4.0F;
kpiCurve.Symbol.Fill = new Fill(Color.White);
pwrCurve.Line.Width = 2.0F;
pwrCurve.Symbol.Size = 4.0F;
pwrCurve.Symbol.Fill = new Fill(Color.White);
pwrCurve.IsY2Axis = true;
myPane.Chart.Fill = new Fill(Color.White, Color.FromArgb(255, 255, 210), -45F);
zdc_graph.AxisChange();
zdc_graph.Refresh();
}
I hope this makes sense. Thanks for the help.
ZedGraph is attempting to detect magnitude and simplify the graph. You can turn this off with the following:
myPane.YAxis.Scale.MagAuto = false;
This will result in y-axis labels like 100000.
If you want to format the label with a separator comma like 100,000:
myPane.YAxis.Scale.Format = "#,#";
Finally, if you prefer to show 100k, you'll need to subscribe to the ScaleFormatEvent and return your own format, like this:
myPane.YAxis.ScaleFormatEvent += new Axis.ScaleFormatHandler(YAxis_ScaleFormatEvent);
string YAxis_ScaleFormatEvent(GraphPane pane, Axis axis, double val, int index)
{
return String.Format("{0}k", val / 1000);
}
I am having similar problem. So applying your method it works on the application but i also want to print out the graph in a PDF file (using MigraDoc) but it does work.
public Bitmap printGraphPane()
{
ZedGraphControl graph = new ZedGraphControl();
GraphPane newGP = myPane.GraphPane;
//newGP.YAxis.Scale.Mag = 0;
//newGP.YAxis.Scale.Format = "#";
//newGP.YAxis.ScaleFormatEvent += new Axis.ScaleFormatHandler(YAxis_ScaleFormatEvent);
Bitmap bit = new Bitmap(newGraph.Width, newGraph.Height);
newGraph.ClientSize = bit.Size;
newGraph.DrawToBitmap(bit, new Rectangle(0, 0, newGraph.Width, newGraph.Height));
return bit;
}