Render OxyPlot graph in Windows Form - c#

I would like to dock an OxyPlot graph in my windows form and graph the function y = 2x - 7. I have downloaded OxyPlot and added the references to my project. I use the following code to add the plot to my form:
public partial class GraphForm : Form
{
public OxyPlot.WindowsForms.Plot Plot;
public Graph()
{
InitializeComponent();
Plot = new OxyPlot.WindowsForms.Plot();
Plot.Model = new PlotModel();
Plot.Dock = DockStyle.Fill;
this.Controls.Add(Plot);
Plot.Model.PlotType = PlotType.XY;
Plot.Model.Background = OxyColor.FromRgb(255, 255, 255);
Plot.Model.TextColor = OxyColor.FromRgb(0, 0, 0);
}
}
With this code I see the white background, the control has been created, but it's only a white background. I've looked around the members of the OxyPlot.Plot class but I couldn't find a way to plat my equation. How can I plot my equation in the graph?

You need to add some data to display, you add this to the Models Series property.
Line (X,Y) graph example.
public Graph()
{
InitializeComponent();
Plot = new OxyPlot.WindowsForms.Plot();
Plot.Model = new PlotModel();
Plot.Dock = DockStyle.Fill;
this.Controls.Add(Plot);
Plot.Model.PlotType = PlotType.XY;
Plot.Model.Background = OxyColor.FromRGB(255, 255, 255);
Plot.Model.TextColor = OxyColor.FromRGB(0, 0, 0);
// Create Line series
var s1 = new LineSeries { Title = "LineSeries", StrokeThickness = 1 };
s1.Points.Add(new DataPoint(2,7));
s1.Points.Add(new DataPoint(7, 9));
s1.Points.Add(new DataPoint(9, 4));
// add Series and Axis to plot model
Plot.Model.Series.Add(s1);
Plot.Model.Axes.Add(new LinearAxis(AxisPosition.Bottom, 0.0, 10.0));
Plot.Model.Axes.Add(new LinearAxis(AxisPosition.Left, 0.0, 10.0));
}
This Example:

Related

Add grid lines to y-axis in NPOI bar chart

I'd like to add horizontal grid lines to a bar chart (IChart) I created using NPOI. I can't find anything in the documentation about adding grid lines to a chart, and I'm wondering if I'm missing something. My code is shown below:
IDrawing drawing = sheet.CreateDrawingPatriarch();
IClientAnchor anchor = drawing.CreateAnchor(0, 0, 0, 0, 4, chartRow, 10, chartRow + 30);
IChart chart = drawing.CreateChart(anchor);
IBarChartData<string, double> data = chart.ChartDataFactory.CreateBarChartData<string, double>();
IChartAxis xAxis = chart.ChartAxisFactory.CreateCategoryAxis(AxisPosition.Bottom);
xAxis.MajorTickMark = AxisTickMark.None;
xAxis.MinorTickMark = AxisTickMark.None;
IValueAxis yAxis = chart.ChartAxisFactory.CreateValueAxis(AxisPosition.Left);
yAxis.MajorTickMark = AxisTickMark.Cross;
yAxis.MinorTickMark = AxisTickMark.None;
yAxis.Crosses = AxisCrosses.AutoZero;
yAxis.SetCrossBetween(AxisCrossBetween.Between);
IChartDataSource<string> xSource = DataSources.FromStringCellRange(sheet, new CellRangeAddress(chartRow + 1, lastRow, 0, 0));
IChartDataSource<double> ySource = DataSources.FromNumericCellRange(sheet, new CellRangeAddress(chartRow + 1, lastRow, 1, 1));
IBarChartSeries<string, double> series = data.AddSeries(xSource, ySource);
series.SetTitle("Matches By World-Check Category"); // This doesn't display for some reason
chart.Plot(data, xAxis, yAxis);
Displaying minor and major gridlines for chart is not supported.
I would suggest to create a ticket for an enhancement.
You can add the gridlines with something like this
chart.GetCTChart().plotArea.valAx[0].AddNewMajorGridlines(); // Alongside Y
chart.GetCTChart().plotArea.catAx[0].AddNewMajorGridlines(); // Alongside X

Multiple 3D objects with C# and WPF

I'm trying to use C# and WPF to render two triangle mesh objects with different colors, and I can't quite figure out how to make it work.
If I set numObjects to 1, it will display a single red triangle as it should.
But, when I set numObjects to 2, the first red triangle is not displayed and only the 2nd green triangle is displayed.
What am I doing wrong here?
Here's my code:
using System.Windows.Media.Media3D;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
// Declare scene objects.
Viewport3D myViewport3D = new Viewport3D();
Model3DGroup myModel3DGroup = new Model3DGroup();
GeometryModel3D myGeometryModel = new GeometryModel3D();
ModelVisual3D myModelVisual3D = new ModelVisual3D();
// Defines the camera used to view the 3D object. In order to view the 3D object,
// the camera must be positioned and pointed such that the object is within view
// of the camera.
PerspectiveCamera myPCamera = new PerspectiveCamera();
public MainWindow()
{
InitializeComponent();
// Specify where in the 3D scene the camera is.
myPCamera.Position = new Point3D(0, 0, 5);
// Specify the direction that the camera is pointing.
myPCamera.LookDirection = new Vector3D(0, 0, -1);
// Define camera's horizontal field of view in degrees.
myPCamera.FieldOfView = 60;
// Asign the camera to the viewport
myViewport3D.Camera = myPCamera;
// Define the lights cast in the scene. Without light, the 3D object cannot
// be seen. Note: to illuminate an object from additional directions, create
// additional lights.
DirectionalLight myDirectionalLight = new DirectionalLight();
myDirectionalLight.Color = Colors.White;
myDirectionalLight.Direction = new Vector3D(-0.61, -0.5, -0.61);
myModel3DGroup.Children.Add(myDirectionalLight);
int numObjects = 2;
for(int i = 0; i < numObjects; i++)
{
BuildObject(i);
}
// Add the group of models to the ModelVisual3d.
myModelVisual3D.Content = myModel3DGroup;
//
myViewport3D.Children.Add(myModelVisual3D);
// Apply the viewport to the page so it will be rendered.
this.Content = myViewport3D;
}
private void BuildObject(int i)
{
// The geometry specifes the shape of the 3D plane. In this sample, a flat sheet
// is created.
MeshGeometry3D myMeshGeometry3D = new MeshGeometry3D();
// Create a collection of normal vectors for the MeshGeometry3D.
Vector3DCollection myNormalCollection = new Vector3DCollection();
myNormalCollection.Add(new Vector3D(0, 0, 1));
myNormalCollection.Add(new Vector3D(0, 0, 1));
myNormalCollection.Add(new Vector3D(0, 0, 1));
myMeshGeometry3D.Normals = myNormalCollection;
double basex = 0 + i * 1;
// Create a collection of vertex positions for the MeshGeometry3D.
Point3DCollection myPositionCollection = new Point3DCollection();
myPositionCollection.Add(new Point3D(basex + -0.5, -0.5, 0.5));
myPositionCollection.Add(new Point3D(basex + 0.5, -0.5, 0.5));
myPositionCollection.Add(new Point3D(basex + 0.5, 0.5, 0.5));
myMeshGeometry3D.Positions = myPositionCollection;
// Create a collection of texture coordinates for the MeshGeometry3D.
PointCollection myTextureCoordinatesCollection = new PointCollection();
myTextureCoordinatesCollection.Add(new Point(0, 0));
myTextureCoordinatesCollection.Add(new Point(1, 0));
myTextureCoordinatesCollection.Add(new Point(1, 1));
myMeshGeometry3D.TextureCoordinates = myTextureCoordinatesCollection;
// Create a collection of triangle indices for the MeshGeometry3D.
Int32Collection myTriangleIndicesCollection = new Int32Collection();
myTriangleIndicesCollection.Add(0);
myTriangleIndicesCollection.Add(1);
myTriangleIndicesCollection.Add(2);
myMeshGeometry3D.TriangleIndices = myTriangleIndicesCollection;
// Apply the mesh to the geometry model.
myGeometryModel.Geometry = myMeshGeometry3D;
// The material specifies the material applied to the 3D object. In this sample a
// linear gradient covers the surface of the 3D object.
Color color = Color.FromArgb(255, 255, 0, 0);
if(i == 1)
{
color = Color.FromArgb(255, 0, 255, 0);
}
SolidColorBrush solid_brush = new SolidColorBrush(color);
DiffuseMaterial solid_material = new DiffuseMaterial(solid_brush);
myGeometryModel.Material = solid_material;
// Add the geometry model to the model group.
myModel3DGroup.Children.Add(myGeometryModel);
Console.WriteLine(myGeometryModel.ToString());
}
}
}
You instantiate and work only with a single GeometryModel3D object (referenced by the field myGeometryModel). So, the data of the green triangle essentially replaces the red triangle data in myGeometryModel.
To fix the issue, delete the myGeometryModel field, and create a GeometryModel3D object for each triangle within the BuildObject method:
public partial class MainWindow : Window
{
Viewport3D myViewport3D = new Viewport3D();
Model3DGroup myModel3DGroup = new Model3DGroup();
ModelVisual3D myModelVisual3D = new ModelVisual3D();
PerspectiveCamera myPCamera = new PerspectiveCamera();
...
private void BuildObject(int i)
{
var myGeometryModel = new GeometryModel3D();
...
}
}

ZXing-Core BitMatrix to BitMap

I am using ZXing-Core(0.14.0.2) to create a barcode which gives me a BitMatrix, however I have not found documentation as to how to extract the image part from the BitMatrix and use it as BitMap so I can incorporate in my bigger image. Eventually what I would like to end up with would be something like this:
The code I currently have is:
img = new Bitmap(300, 375);
drawing = Graphics.FromImage(img);
var barCode = new Code128Writer().encode(packageModel.TrackingId.PrintValue, BarcodeFormat.CODE_128, 280, 70);
src = transform **barCode** to **Drawing.Image**
drawing.DrawImage(src, new Rectangle(10, 255, 280, 70));
UPDATE
I now have this code, however I am getting an error You have to set a renderer instance. I dont understand why the interface is not instantiating this class by itself. There is not documentation available revealing how this is supposed to work. I cant use the Write functions because the Rendering is set to null, however I am not sure how to instantiate it.
IBarcodeWriterGeneric<Image> barcodeWriterGeneric = new BarcodeWriterGeneric<Image>
{
Format = BarcodeFormat.CODE_128,
Options = new EncodingOptions
{
Width = 280,
Height = 70
},
Renderer = new PixelData() //HOW DOES THE RENDERER WORK????
};
var test = barcodeWriterGeneric.Write("WORKS");
drawing.DrawImage(test, new Rectangle(10, 255, 280, 70));
Create a renderer that implements IBarcodeRenderer<TOut>. This one works for me in iOS.
var writer = new BarcodeWriter<UIImage>()
{
Format = ZXing.BarcodeFormat.CODE_128,
Options = new EncodingOptions
{
Height = height,
Width = width,
Margin = 0
},
Renderer = new BarcodeRenderer()
};
var image = writer.Write(barcodeValue);
private class BarcodeRenderer : IBarcodeRenderer<UIImage>
{
public UIImage Render(BitMatrix matrix, ZXing.BarcodeFormat format, string content)
{
return RenderMatrix(matrix);
}
public UIImage Render(BitMatrix matrix, ZXing.BarcodeFormat format, string content, EncodingOptions options)
{
return RenderMatrix(matrix);
}
}
/// <summary>
/// Renders the bitmatrix.
/// </summary>
private static UIImage RenderMatrix(BitMatrix matrix)
{
var width = matrix.Width;
var height = matrix.Height;
var black = new CGColor(0f, 0f, 0f);
var white = new CGColor(1.0f, 1.0f, 1.0f);
UIGraphics.BeginImageContext(new CGSize(width, height));
var context = UIGraphics.GetCurrentContext();
for (var x = 0; x < width; x++)
{
for (var y = 0; y < height; y++)
{
context.SetFillColor(matrix[x, y] ? black : white);
context.FillRect(new CGRect(x, y, 1, 1));
}
}
var img = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return img;
}
As far as I can see the ZXing-Core fork is missing the PixelDataRenderer class. It contains only the RawRenderer. You should switch to the original ZXing.Net package with the current version 0.15.0. That one contains the barcode writer class "BarcodeWriterPixelData" which does the necessary initialization of the Renderer property. Next version of ZXing.Net will contain some more specialized bindings to other .Net Core compatible imaging libraries like CoreCompat.System.Drawing, ImageSharp, OpenCV and more. With that bindings you can then generate other output formats besides PixelData.

Convert Ellipse or EllipseGeometry to PathFigure on Windows Phone 8.1

I've stumbled upon converting Ellipse to PathGeometry.
I've tried to use ArcSegment to present Ellipse, but still don't know how to convert Ellipse size to ArcSegment size. I'm trying to segment Ellipse into two part, but there are other approaches, i.e. Bezier curves.
Need clues how to convert Ellipse to ArcSegment collection.
The whole process could be looking like that:
public static PathFigure ToFigures(this Ellipse ellipse)
{
var pathFigure = new PathFigure {IsClosed = true};
var arcSegment1 = new ArcSegment();
var arcSegment2 = new ArcSegment();
pathFigure.Segments.Add(arcSegment1);
pathFigure.Segments.Add(arcSegment2);
return pathFigure;
}
You could directly use an EllipseGeometry for the Path Data:
path = new Path
{
Data = new EllipseGeometry { RadiusX = 100, RadiusY = 50 }
};
Using the size of the Ellipse it would look like this:
path = new Path
{
Data = new EllipseGeometry
{
RadiusX = ellipse.ActualWidth / 2,
RadiusY = ellipse.ActualHeight / 2
}
};

Curved Line (Bezier) Gradient

How to draw a bezier with two colors? like the picture below?
I already have drawn the bezier, I can fill it with any color, however I cant the gradient working.
this is what im doing, im using a Path to create the bezier by the way.
private void test()
{
System.Windows.Media.GradientStop GradientStop1 = new System.Windows.Media.GradientStop();
System.Windows.Media.GradientStop GradientStop2 = new System.Windows.Media.GradientStop();
System.Windows.Media.LinearGradientBrush p_Fill; p_Fill = new System.Windows.Media.LinearGradientBrush(Colors.Blue, Colors.Red, new Point(0, 0.5), new Point(1, 0.5));
p_Fill.GradientStops.Add(GradientStop1);
p_Fill.GradientStops.Add(GradientStop2);
Bez.Fill = p_Fill;
}
This is how it should be
This is what I get
If you need a sharp cut between the 2 colored halves, you have to need more GradientStops:
var grad3 = new System.Windows.Media.GradientStop()
{Offset = 0.5, Color=Colors.Blue};
var grad4 = new System.Windows.Media.GradientStop()
{Offset = 0.5, Color=Colors.Red};
GradientStop2.Offset = 1;
p_Fill.GradientStops.Add(GradientStop1);
p_Fill.GradientStops.Add(grad3);
p_Fill.GradientStops.Add(grad4);
p_Fill.GradientStops.Add(GradientStop2);
Addtionally, you have to set the Brush for the Stroke, not the Fill. The StrokeThickness determines the thickness of the curve:
Bez.Stroke = p_Fill;
Bez.StrokeThickness = new Thickness(10);

Categories