I'm trying to draw a polygon with more than one holes. I tried the following code and it does not work correctly. Please advise.
PointF[] mypoly = new PointF[6 + 5 + 5];
mypoly[0] = new PointF(0, 0);
mypoly[1] = new PointF(100, 0);
mypoly[2] = new PointF(100, 100);
mypoly[3] = new PointF(0, 100);
mypoly[4] = new PointF(10, 80);
mypoly[5] = new PointF(0, 0);
mypoly[6] = new PointF(10, 10);
mypoly[7] = new PointF(10, 20);
mypoly[8] = new PointF(20, 20);
mypoly[9] = new PointF(20, 10);
mypoly[10] = new PointF(10, 10);
mypoly[11] = new PointF(40, 10);
mypoly[12] = new PointF(40, 20);
mypoly[13] = new PointF(60, 20);
mypoly[14] = new PointF(60, 10);
mypoly[15] = new PointF(40, 10);
g.FillPolygon(new SolidBrush(Color.Red), mypoly, FillMode.Winding);
The first part is the outer polygon. The second and the third parts are the two holes inside the polygon.
Use a GraphicsPath instead. You can draw it with Graphics.FillPath, like this:
using System.Drawing.Drawing2D;
...
using (var gp = new GraphicsPath()) {
PointF[] outer = new PointF[] { new PointF(0, 0), new PointF(100, 0),
new PointF(100, 100), new PointF(0, 100), new PointF(10, 80),new PointF(0, 0) };
gp.AddPolygon(outer);
PointF[] inner1 = new PointF[] { new PointF(10, 10), new PointF(10, 20),
new PointF(20, 20), new PointF(20, 10), new PointF(10, 10) };
gp.AddPolygon(inner1);
PointF[] inner2 = new PointF[] { new PointF(40, 10), new PointF(40, 20),
new PointF(60, 20), new PointF(60, 10), new PointF(40, 10) };
gp.AddPolygon(inner2);
e.Graphics.FillPath(Brushes.Black, gp);
}
Related
I need to create a framed GraphicsPath that self-intersects giving a z-order feeling:
The code that I used to obtain the image is the following:
private void Example1(PaintEventArgs e) {
Brush brush = new SolidBrush(Color.FromArgb(200, Color.LightBlue));
GraphicsPath path1 = new GraphicsPath(FillMode.Winding);
path1.AddLines(new Point[] {
new Point(400, 200),
new Point(400, 300),
new Point(100, 300),
new Point(100, 400),
new Point(500, 400),
new Point(500, 100)
});
e.Graphics.FillPath(brush, path1);
e.Graphics.DrawPath(Pens.Blue, path1);
GraphicsPath path2 = new GraphicsPath(FillMode.Winding);
path2.AddLines(new Point[] {
new Point(500, 100),
new Point(200, 100),
new Point(200, 500),
new Point(300, 500),
new Point(300, 200),
new Point(400, 200)
});
e.Graphics.FillPath(brush, path2);
e.Graphics.DrawPath(Pens.Blue, path2);
}
in which I draw the two paths independently.
My need is to handle it as a unique graphic object, but if I join the paths I obtain this image:
Example code:
private void Example2(PaintEventArgs e) {
Brush brush = new SolidBrush(Color.FromArgb(200, Color.LightBlue));
GraphicsPath path1 = new GraphicsPath(FillMode.Winding);
path1.AddLines(new Point[] {
new Point(400, 200),
new Point(400, 300),
new Point(100, 300),
new Point(100, 400),
new Point(500, 400),
new Point(500, 100)
});
GraphicsPath path2 = new GraphicsPath(FillMode.Winding);
path2.AddLines(new Point[] {
new Point(500, 100),
new Point(200, 100),
new Point(200, 500),
new Point(300, 500),
new Point(300, 200),
new Point(400, 200)
});
path1.AddPath(path2, true);
e.Graphics.FillPath(brush, path1);
e.Graphics.DrawPath(Pens.Blue, path1);
}
Same problem if I use StartFigure/CloseFigure. Maybe I can solve the problem using the SetMarkers method in conjunction with the GraphicsPathIterator, but it seems overwhelming.
The simplest way that I found is to use the GraphicsPathIterator. In this way I can store more figures on a single path and have the flexibility I need during the painting. The only drawback is that the paint method has to be modified accordingly.
Here is an example in which I define the path and that do also the painting:
private void Example4(PaintEventArgs e) {
Brush brush = new SolidBrush(Color.FromArgb(200, Color.LightBlue));
GraphicsPath path = new GraphicsPath(FillMode.Winding);
path.StartFigure();
path.AddLines(new Point[] {
new Point(400, 200),
new Point(400, 300),
new Point(100, 300),
new Point(100, 400),
new Point(500, 400),
new Point(500, 100)
});
path.StartFigure();
path.AddLines(new Point[] {
new Point(500, 100),
new Point(200, 100),
new Point(200, 500),
new Point(300, 500),
new Point(300, 200),
new Point(400, 200)
});
GraphicsPathIterator pathIterator = new GraphicsPathIterator(path);
GraphicsPath p = new GraphicsPath();
while (pathIterator.NextSubpath(p, out bool isClosed) > 0) {
e.Graphics.FillPath(brush, p);
e.Graphics.DrawPath(Pens.Blue, p);
}
}
Right now I am using Viewport3D in which I am drawing all 3D shapes but I also want to draw arc, point and lines in Viewport3D. Can anyone help me with this?
private Viewport2DVisual3D ArcModel;
private Model3DGroup group;
MeshGeometry3D testGeometry = new MeshGeometry3D();
PathFigure pthFigure = new PathFigure();
pthFigure.StartPoint = new Point(1, 1);
ArcSegment arcSeg = new ArcSegment();
arcSeg.Point = new Point(30, 30);
arcSeg.Size = new Size(20, 20);
arcSeg.IsLargeArc = true;
arcSeg.SweepDirection = SweepDirection.Counterclockwise;
//arcSeg.RotationAngle = 30;
PathSegmentCollection myPathSegmentCollection = new PathSegmentCollection();
myPathSegmentCollection.Add(arcSeg);
pthFigure.Segments = myPathSegmentCollection;
PathFigureCollection pthFigureCollection = new PathFigureCollection();
pthFigureCollection.Add(pthFigure);
PathGeometry pthGeometry = new PathGeometry();
pthGeometry.Figures = pthFigureCollection;
Path arcPath = new Path();
arcPath.Stroke = new SolidColorBrush(Colors.Violet);
arcPath.StrokeThickness = 1;
arcPath.Data = pthGeometry;
//arcPath.Fill = new SolidColorBrush(Colors.Yellow);
//Children.Add(arcPath);
Point3DCollection myPoint3DCollection = new Point3DCollection();
myPoint3DCollection.Add(new Point3D(0, 0, 0));
myPoint3DCollection.Add(new Point3D(0, 0, 2));
myPoint3DCollection.Add(new Point3D(0, 2, 0));
myPoint3DCollection.Add(new Point3D(0, 2, 2));
testGeometry.Positions = myPoint3DCollection;
PointCollection myPointCollection = new PointCollection();
myPointCollection.Add(new Point(0, 1));
myPointCollection.Add(new Point(1, 1));
myPointCollection.Add(new Point(0, 0));
myPointCollection.Add(new Point(1, 0));
testGeometry.TextureCoordinates = myPointCollection;
Int32Collection triangleIndicesCollection = new Int32Collection();
triangleIndicesCollection.Add(0);
triangleIndicesCollection.Add(1);
triangleIndicesCollection.Add(2);
triangleIndicesCollection.Add(2);
triangleIndicesCollection.Add(1);
triangleIndicesCollection.Add(3);
testGeometry.TriangleIndices = triangleIndicesCollection;
DiffuseMaterial myDiffuseMaterial = new DiffuseMaterial(Brushes.White);
Viewport2DVisual3D.SetIsVisualHostMaterial(myDiffuseMaterial, true);
ArcModel = new Viewport2DVisual3D();
ArcModel.Material = myDiffuseMaterial;
ArcModel.Geometry = testGeometry;
//group.Children.Add(ArcModel.Geometry);
ArcModel.Visual = arcPath;
ArcGeomodel = new GeometryModel3D(ArcModel.Geometry, myDiffuseMaterial);
ArcGeomodel.Transform = new Transform3DGroup();
group.Children.Add(ArcGeomodel);
viewport.Children.Add(ArcModel);
I am drawing this arc using path geometry and adding it into Viewport2DVisual3D but its not getting displayed...
what I am missing here ...please suggest any solution
Finally got what I was missing.I was missing to add transformation and rotation to it
following is the code
Transform3DGroup myTransform3DGroup = new Transform3DGroup();
RotateTransform3D rotateTransform = new RotateTransform3D()
{
Rotation = new AxisAngleRotation3D
{
Angle = 40,
Axis = new Vector3D(0, 1, 0)
}
};
myTransform3DGroup.Children.Add(rotateTransform);
ArcModel.Transform = myTransform3DGroup;
ArcModel.Material = myDiffuseMaterial;
ArcModel.Geometry = testGeometry;
ArcModel.Visual = arcPath;
viewport.Children.Add(ArcModel);
Hope this will help someone!
I am searching the shortest way in my polygon (route). It starts on the center border on bottom left (blue) and ends on the center border on the top right (red). It is not allowed to leave the route.
Which algorithm i can use to calculate this route? I need a list of points to draw the shortest way. A example code would be great.
Example of my polygon with start and end
var points = new List<Point> { new Point(210, 540), new Point(330, 420), new Point(360, 420), new Point(420, 390), new Point(450, 330), new Point(480, 315), new Point(510, 270), new Point(570, 240), new Point(630, 240), new Point(690, 180), new Point(750, 150), new Point(810, 120), new Point(864, 120), new Point(864, 60), new Point(810, 60), new Point(750, 90), new Point(690, 120), new Point(630, 150), new Point(570, 150), new Point(510, 210), new Point(480, 255), new Point(450, 270), new Point(420, 330), new Point(360, 360), new Point(330, 360), new Point(156, 480) };
var image = new Bitmap(1000, 600);
using (var graphics = Graphics.FromImage(image))
{
graphics.Clear(Color.White);
graphics.FillPie(Brushes.Blue, 190, 500, 10, 10, 0, 360);
graphics.FillPie(Brushes.Red, 840, 80, 10, 10, 0, 360);
graphics.DrawPolygon(new Pen(Color.Black, 2), points.ToArray());
}
image.Save("example.bmp");
Solution
Thanks #gusman
Add Raster
Calculate distance between points
Search best route with Dijkstra.NET
using Dijkstra.NET.Contract;
using Dijkstra.NET.Model;
using Dijkstra.NET.ShortestPath;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace Test.Polygon
{
class Program
{
static void Main(string[] args)
{
var points = new List<Point> { new Point(210, 540), new Point(330, 420), new Point(360, 420), new Point(420, 390), new Point(450, 330), new Point(480, 315), new Point(510, 270), new Point(570, 240), new Point(630, 240), new Point(690, 180), new Point(750, 150), new Point(810, 120), new Point(864, 120), new Point(864, 60), new Point(810, 60), new Point(750, 90), new Point(690, 120), new Point(630, 150), new Point(570, 150), new Point(510, 210), new Point(480, 255), new Point(450, 270), new Point(420, 330), new Point(360, 360), new Point(330, 360), new Point(156, 480) };
var start = new Point(190, 500);
var target = new Point(840, 80);
var image = new Bitmap(1000, 600);
using (var graphics = Graphics.FromImage(image))
{
graphics.Clear(Color.White);
graphics.FillPie(Brushes.Blue, 190, 500, 10, 10, 0, 360);
graphics.FillPie(Brushes.Red, 840, 80, 10, 10, 0, 360);
graphics.DrawPolygon(new Pen(Color.Black, 2), points.ToArray());
}
var path = new GraphicsPath(FillMode.Winding);
path.AddPolygon(points.ToArray());
var pointsForConnect = DrawRaster(5, image, path);
var dictionary = new Dictionary<uint, Point>();
dictionary.Add(0, start);
dictionary.Add(1, target);
var graph = new Graph<int, string>();
var i = 2;
foreach (var point in pointsForConnect)
{
dictionary.Add((uint)i, point);
graph.AddNode(i);
i++;
}
foreach (var point in dictionary)
{
foreach (var point2 in dictionary)
{
if (point.Equals(point2))
{
continue;
}
double dist = Math.Sqrt(Math.Pow(point2.Value.X - point.Value.X, 2) + Math.Pow(point2.Value.Y - point.Value.Y, 2));
if (dist > 50)
{
continue;
}
graph.Connect(point.Key, point2.Key, (int)dist, null);
//graph.Connect()
}
}
var dijkstra = new Dijkstra<int, string>(graph);
IShortestPathResult result = dijkstra.Process(0, 1); //result contains the shortest path
var shortestRouteIds = result.GetPath();
var shortestRoutePoints = new List<Point>();
foreach(var x in shortestRouteIds)
{
shortestRoutePoints.Add(dictionary[x]);
}
DrawDriver(shortestRoutePoints, image);
image.Save("example.bmp");
}
private static void DrawDriver(List<Point> points, Bitmap image)
{
var pen = new Pen(Color.LightGreen, 5);
for (var i = 0; i < points.Count - 1; i++)
{
var x = points[i].X;
var y = points[i].Y;
var x1 = points[i + 1].X;
var y1 = points[i + 1].Y;
DrawLineInt(image, new Point(x, y), new Point(x1, y1), pen);
}
}
private static void DrawLineInt(Bitmap bmp, Point p1, Point p2, Pen pen)
{
using (var graphics = Graphics.FromImage(bmp))
{
graphics.DrawLine(pen, p1.X, p1.Y, p2.X, p2.Y);
}
}
private static List<Point> DrawRaster(int edge, Bitmap image, GraphicsPath path)
{
var points = new List<Point>();
var countHorizontal = image.Width / edge;
var countVertical = image.Height / edge;
using (var graphics = Graphics.FromImage(image))
{
for (int x = 0; x < countHorizontal; x++)
{
for (int y = 0; y < countVertical; y++)
{
var boxX = (x * edge) + (edge / 2);
var boxY = (y * edge) + (edge / 2);
if (!path.IsVisible(boxX, boxY))
{
continue;
}
points.Add(new Point(boxX, boxY));
graphics.DrawRectangle(Pens.LightGray, x * edge, y * edge, edge, edge);
}
}
}
return points;
}
}
}
I want to print some data in printer 1 and some data in printer 2.
public void printkot()
{
PrintDialog pd = new PrintDialog();
PrintDocument pdoc = new PrintDocument();
PrinterSettings ps = new PrinterSettings();
Font font = new Font("Arial", 12);
PaperSize psize = new PaperSize("Custome", 314, 500);
pd.Document = pdoc;
for (int ch = 0; dataGridView1.Rows.Count > ch; ch++)
{
if (dataGridView1.Rows[ch].Cells["calkot_print"].Value.ToString() == "K1")
{
pdoc.PrinterSettings.PrinterName = "KOT";
pdoc.PrintPage += new PrintPageEventHandler(printDocument1_PrintPage);
}
}
pd.Document.DefaultPageSettings.PaperSize = psize;
pdoc.DefaultPageSettings.PaperSize.Height = 500;
pdoc.DefaultPageSettings.PaperSize.Width = 314;
if (pdoc.PrinterSettings.IsValid)
{
pdoc.Print();
}
else
{
MessageBox.Show("Printer is invalid.");
}
}
private void printDocument1_PrintPage2(object sender, PrintPageEventArgs e)
{
string table_no;
table_no = lbltable.Text;
float xs = 10;
float ys = 5;
float widths = 285.0F; // max width I found through trial and error
float heights = 0F;
DataTable dtm = blu.checkbusiness();
Font drawFontArial12Bold = new Font("Arial", 12, FontStyle.Bold);
Font drawFontArial10Regular = new Font("Arial", 9, FontStyle.Regular);
Font drawFontArial10Regularsmall = new Font("Arial", 6, FontStyle.Regular);
SolidBrush drawBrush = new SolidBrush(Color.Black);
Pen drawingPen = new Pen(Color.Black, 1);
// Set format of string.
StringFormat drawFormatCenter = new StringFormat();
drawFormatCenter.Alignment = StringAlignment.Center;
StringFormat drawFormatLeft = new StringFormat();
drawFormatLeft.Alignment = StringAlignment.Near;
StringFormat drawFormatRight = new StringFormat();
drawFormatRight.Alignment = StringAlignment.Far;
StringFormat drawFormatRightlest = new StringFormat();
string business_name = dtm.Rows[0]["business_name"].ToString();
string address = dtm.Rows[0]["address"].ToString();
Graphics gra = e.Graphics;
String strDate = DateTime.Now.ToLongTimeString();
gra.DrawString(strDate, new System.Drawing.Font("Arial", 7, FontStyle.Regular), new SolidBrush(System.Drawing.Color.Black), 10, 60);
e.Graphics.DrawString(business_name, drawFontArial12Bold, drawBrush, new RectangleF(xs, ys, widths, heights), drawFormatCenter);
ys += e.Graphics.MeasureString(business_name, drawFontArial12Bold).Height;
e.Graphics.DrawString(address, drawFontArial10Regular, drawBrush, new RectangleF(xs, ys, widths, heights), drawFormatCenter);
ys += e.Graphics.MeasureString(address, drawFontArial10Regular).Height;
gra.DrawString("Table No::", new System.Drawing.Font("Arial", 9, FontStyle.Regular), new SolidBrush(System.Drawing.Color.Black), 190, 60);
gra.DrawString(table_no, new System.Drawing.Font("Arial", 9, FontStyle.Regular), new SolidBrush(System.Drawing.Color.Black), 250, 45);
gra.DrawLine(drawingPen, 10, 75, 309, 75);
gra.DrawString("Item", new System.Drawing.Font("Arial", 9, FontStyle.Bold), new SolidBrush(System.Drawing.Color.Black), 30, 75);
gra.DrawString("Qty", new System.Drawing.Font("Arial", 9, FontStyle.Bold), new SolidBrush(System.Drawing.Color.Black), 220, 75);
gra.DrawLine(drawingPen, 10, 90, 309, 90);
int y;
y = 95;
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
string item_name = dataGridView1.Rows[i].Cells["cal_item_name"].Value.ToString();
string quantity = dataGridView1.Rows[i].Cells["cal_qty"].Value.ToString();
if (dataGridView1.Rows[i].Cells["calkot_print"].Value.ToString() == "K2")
{
gra.DrawString(item_name.ToString(), new System.Drawing.Font("Time New Roamn", 9, FontStyle.Regular), new SolidBrush(System.Drawing.Color.Black), 30, y);
gra.DrawString(quantity, new System.Drawing.Font("Time New Roamn", 9, FontStyle.Regular), new SolidBrush(System.Drawing.Color.Black), 220, y);
y = y + 15;
}
}
int z = y + 20;
gra.DrawLine(drawingPen, 10, z, 309, z);
gra.DrawString("Description", new System.Drawing.Font("Time New Roamn", 9, FontStyle.Bold), new SolidBrush(System.Drawing.Color.Black), 10, z + 5);
gra.DrawString(txtrichbox.Text, new System.Drawing.Font("Time New Roamn", 7, FontStyle.Regular), new SolidBrush(System.Drawing.Color.Black), 10, z + 20);
z = y + 20;
}
I have a problem with AntiAliasing smoothing mode and drawing.
Let say I have a signal with min and max values at the same points.
So I want to display it to see where it "thicker".
So the method I use is to draw vertical lines and use antialiasing.
Here is the problem, the rising edge seems to be antialiased, but the falling not.
If I added some noise to the second signal the same thing observable.
Without noise
With noise
![With noise][2]
Can anyone point out what am I missing? Or this problem comes from somewhere else?
Code (moved from comments):
Bitmap drawBitmap = new Bitmap(pictureBox1.Height, _
pictureBox1.Width, _
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Graphics drawGraph;
Point[] pts = new Point[] { new Point(0, 60), new Point(0, 59), new Point(1, 35), _
new Point(1, 47), new Point(2, 25), new Point(2, 35), _
new Point(3, 17), new Point(3, 25), new Point(4, 12), _
new Point(4, 27), new Point(5, 10), new Point(5, 22), _
new Point(6, 10), new Point(6, 11), new Point(7, 11), _
new Point(7, 16), new Point(8, 16), new Point(8, 24), _
new Point(9, 24), new Point(9, 34), new Point(10, 34), _
new Point(10, 46), new Point(11, 46), new Point(11, 59), _
new Point(12, 59), new Point(12, 72)};
using (drawGraph = Graphics.FromImage(drawBitmap)) {
drawGraph.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic;
drawGraph.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias;
for (int i = 1; i < pts.Length - 1; i += 2) {
drawGraph.DrawLine(new Pen(Color.Black, 1), pts[i], pts[i - 1]);
drawGraph.DrawLine(new Pen(Color.Black, 1), pts[i], pts[i + 1]);
}
}
pictureBox1.Image = drawBitmap;
Apply a pixel offset mode as well:
drawGraph.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality;
The InterpolationMode can be removed as it do nothing with lines (only with images when resized).