void DrawingPanel_Paint(object sender, GUI.PaintEventArgs e) { GUI.Cursor.Current = GUI.Cursors.WaitCursor; Graphics graphics = e.Graphics; SmoothingMode fillSmoothingMode = graphics is SoftwareGraphics ? SmoothingMode.AntiAlias : SmoothingMode.None; SmoothingMode strokeSmoothingMode = SmoothingMode.AntiAlias; graphics.SmoothingMode = fillSmoothingMode; graphics.Clear(Color.White); GraphicsPath path = new GraphicsPath(); if (rbNonZero.IsChecked) { path.FillMode = FillMode.Winding; } //draw subjects ... foreach (Polygon pg in subjects) { Point[] pts = PolygonToPointArray(pg, scale); path.AddPolygon(pts); pts = null; } Pen myPen = new Pen( //Color.FromArgb(196, 0xC3, 0xC9, 0xCF), Color.FromArgb(128, 0, 0, 255), 0.6); SolidColorBrush myBrush = new SolidColorBrush( //Color.FromArgb(127, 0xDD, 0xDD, 0xF0)); //Color.FromArgb(255, 210, 210, 255)); Color.FromArgb(127, Color.LightBlue)); graphics.SmoothingMode = fillSmoothingMode; graphics.FillPath(myBrush, path); graphics.SmoothingMode = strokeSmoothingMode; graphics.DrawPath(myPen, path); path.Reset(); //draw clips ... if (rbNonZero.IsChecked) { path.FillMode = FillMode.Winding; } foreach (Polygon pg in clips) { Point[] pts = PolygonToPointArray(pg, scale); path.AddPolygon(pts); pts = null; } myPen.Color = Color.FromArgb(128, Color.Red); //0xF9, 0xBE, 0xA6); myBrush.Color = //Color.FromArgb(127, 0xFF, 0xE0, 0xE0); Color.FromArgb(50, 255, 0, 0); graphics.SmoothingMode = fillSmoothingMode; graphics.FillPath(myBrush, path); graphics.SmoothingMode = strokeSmoothingMode; graphics.DrawPath(myPen, path); //do the clipping ... if ((clips.Count > 0 || subjects.Count > 0) && !rbNone.IsChecked) { Polygons solution2 = new Polygons(); Clipper c = new Clipper(0); c.AddPaths(subjects, PolyType.ptSubject, true); c.AddPaths(clips, PolyType.ptClip, true); solution.Clear(); bool succeeded = c.Execute(GetClipType(), solution, GetPolyFillType(), GetPolyFillType()); if (succeeded) { myBrush.Color = Color.Black; path.Reset(); //It really shouldn't matter what FillMode is used for solution //polygons because none of the solution polygons overlap. //However, FillMode.Winding will show any orientation errors where //holes will be stroked (outlined) correctly but filled incorrectly ... path.FillMode = FillMode.Winding; //or for something fancy ... if (nudOffset.Value != 0) { //old solution2 = Clipper.OffsetPolygons(solution, (double)nudOffset.Value * scale, JoinType.jtMiter); ClipperOffset co = new ClipperOffset(2, 0.25); co.AddPaths(solution, JoinType.jtMiter, EndType.etClosedPolygon); co.Execute(ref solution2, (double)nudOffset.Value * scale); } else { solution2 = new Polygons(solution); } foreach (Polygon pg in solution2) { Point[] pts = PolygonToPointArray(pg, scale); if (pts.Length//Count() > 2) { path.AddPolygon(pts); } pts = null; } //myBrush.Color = Color.FromArgb(127, 0x66, 0xEF, 0x7F); myBrush.Color = Color.FromArgb(100, 0, 255, 0); myPen.Color = Color.FromArgb(255, 0, 0x33, 0); myPen.Width = 1; graphics.SmoothingMode = fillSmoothingMode; graphics.FillPath(myBrush, path); graphics.SmoothingMode = strokeSmoothingMode; graphics.DrawPath(myPen, path); //now do some fancy testing ... Font f = new Font("Arial", 8); Brush b = Brushes.Navy; double subj_area = 0, clip_area = 0, int_area = 0, union_area = 0; c.Clear(); c.AddPaths(subjects, PolyType.ptSubject, true); c.Execute(ClipType.ctUnion, solution2, GetPolyFillType(), GetPolyFillType()); foreach (Polygon pg in solution2) { subj_area += Clipper.Area(pg); } c.Clear(); c.AddPaths(clips, PolyType.ptClip, true); c.Execute(ClipType.ctUnion, solution2, GetPolyFillType(), GetPolyFillType()); foreach (Polygon pg in solution2) { clip_area += Clipper.Area(pg); } c.AddPaths(subjects, PolyType.ptSubject, true); c.Execute(ClipType.ctIntersection, solution2, GetPolyFillType(), GetPolyFillType()); foreach (Polygon pg in solution2) { int_area += Clipper.Area(pg); } c.Execute(ClipType.ctUnion, solution2, GetPolyFillType(), GetPolyFillType()); foreach (Polygon pg in solution2) { union_area += Clipper.Area(pg); } StringFormat lftStringFormat = new StringFormat(); lftStringFormat.Alignment = StringAlignment.Near; lftStringFormat.LineAlignment = StringAlignment.Near; StringFormat rtStringFormat = new StringFormat(); rtStringFormat.Alignment = StringAlignment.Far; rtStringFormat.LineAlignment = StringAlignment.Near; RectI rec = new RectI(WorkArea.Width - 114, WorkArea.Height - 116, 104, 106); graphics.FillRectangle(new SolidColorBrush(Color.FromArgb(196, Color.WhiteSmoke)), rec); graphics.DrawRectangle(myPen, rec); rec.Inflate(new SizeI(-2, 0)); // because of Alt.Sketch smaller top offset rec += new PointI(0, 1); rec -= new SizeI(0, 1); graphics.DrawString("Areas", f, b, rec, rtStringFormat); rec.Offset(new PointI(0, 14)); graphics.DrawString("subj: ", f, b, rec, lftStringFormat); graphics.DrawString((subj_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat); rec.Offset(new PointI(0, 12)); graphics.DrawString("clip: ", f, b, rec, lftStringFormat); graphics.DrawString((clip_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat); rec.Offset(new PointI(0, 12)); graphics.DrawString("intersect: ", f, b, rec, lftStringFormat); graphics.DrawString((int_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat); rec.Offset(new PointI(0, 12)); graphics.DrawString("---------", f, b, rec, rtStringFormat); rec.Offset(new PointI(0, 10)); graphics.DrawString("s + c - i: ", f, b, rec, lftStringFormat); graphics.DrawString(((subj_area + clip_area - int_area) / 100000).ToString("0,0"), f, b, rec, rtStringFormat); rec.Offset(new PointI(0, 10)); graphics.DrawString("---------", f, b, rec, rtStringFormat); rec.Offset(new PointI(0, 10)); graphics.DrawString("union: ", f, b, rec, lftStringFormat); graphics.DrawString((union_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat); rec.Offset(new PointI(0, 10)); graphics.DrawString("---------", f, b, rec, rtStringFormat); } //end if succeeded } //end if something to clip //TEMP pictureBox1.Image = mybitmap; graphics.Dispose(); GUI.Cursor.Current = GUI.Cursors.Default; }