예제 #1
0
        //---------------------------------------------------------------------
        private void DrawBitmap(bool justClip = false)
        {
            if (!justClip)
            {
                if (rbTest2.Checked)
                    GenerateAustPlusRandomEllipses((int)nudCount.Value);
                else
                    GenerateRandomPolygon((int)nudCount.Value);
            }
            Cursor.Current = Cursors.WaitCursor;
            Graphics newgraphic;
            newgraphic = Graphics.FromImage(mybitmap);
            newgraphic.SmoothingMode = SmoothingMode.AntiAlias;
            newgraphic.Clear(Color.WhiteSmoke);
            Pen myPen = new Pen(Color.LightSlateGray, (float)1.5);
            SolidBrush myBrush = new SolidBrush(Color.FromArgb(16, Color.Blue));

            GraphicsPath path = new GraphicsPath();
            if (rbNonZero.Checked) path.FillMode = FillMode.Winding;

            foreach (Polygon pg in subjects)
            {
                PointF[] pts = PolygonToPointFArray(pg, scale);
                path.AddPolygon(pts);
                pts = null;
            }
            newgraphic.FillPath(myBrush, path);
            newgraphic.DrawPath(myPen, path);
            path.Reset();
            if (rbNonZero.Checked) path.FillMode = FillMode.Winding;
            foreach (Polygon pg in clips)
            {
                PointF[] pts = PolygonToPointFArray(pg, scale);
                path.AddPolygon(pts);
                pts = null;
            }
            myPen.Color = Color.LightSalmon;
            myBrush.Color = Color.FromArgb(16, Color.Red);
            newgraphic.FillPath(myBrush, path);
            newgraphic.DrawPath(myPen, path);

            //do the clipping ...
            if ((clips.Count > 0 || subjects.Count > 0) && !rbNone.Checked)
            {
                Polygons solution = new Polygons();
                //Stopwatch sw = new Stopwatch();
                //sw.Start();

                clipper.Clipper c = new clipper.Clipper();
                c.AddPolygons(subjects, PolyType.ptSubject);
                c.AddPolygons(clips, PolyType.ptClip);
                if (!c.Execute(GeClipType(), solution, GePolyFillType(), GePolyFillType()))
                {
                    Console.Beep(1250, 250);
                }

                //sw.Stop();
                //TimeSpan ts = sw.Elapsed;
                //this.Text = Convert.ToString(ts.TotalMilliseconds);

                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)
                    solution = clipper.Clipper.OffsetPolygons(solution, (double)nudOffset.Value * scale);
                foreach (Polygon pg in solution)
                {
                    PointF[] pts = PolygonToPointFArray(pg, scale);
                    if (pts.Count() > 2)
                      path.AddPolygon(pts);
                    pts = null;
                }
                myBrush.Color = Color.FromArgb(128, Color.Yellow);
                myPen.Color = Color.Black;
                newgraphic.FillPath(myBrush, path);
                newgraphic.DrawPath(myPen, path);

                foreach (Polygon pg in solution)
                {
                    PointF[] pts = PolygonToPointFArray(pg, scale);
                    path.Reset();
                    path.AddPolygon(pts);
                }
            }
            pictureBox1.Image = mybitmap;
            newgraphic.Dispose();
            Cursor.Current = Cursors.Default;
        }
예제 #2
0
        //---------------------------------------------------------------------

        private void DrawBitmap(bool justClip = false)
        {
            if (!justClip)
            {
                if (rbTest2.Checked)
                {
                    GenerateAustPlusRandomEllipses((int)nudCount.Value);
                }
                else
                {
                    GenerateRandomPolygon((int)nudCount.Value);
                }
            }
            Cursor.Current = Cursors.WaitCursor;
            Graphics newgraphic;

            newgraphic = Graphics.FromImage(mybitmap);
            newgraphic.SmoothingMode = SmoothingMode.AntiAlias;
            newgraphic.Clear(Color.WhiteSmoke);
            Pen        myPen   = new Pen(Color.LightSlateGray, (float)1.5);
            SolidBrush myBrush = new SolidBrush(Color.FromArgb(16, Color.Blue));

            GraphicsPath path = new GraphicsPath();

            if (rbNonZero.Checked)
            {
                path.FillMode = FillMode.Winding;
            }

            foreach (Polygon pg in subjects)
            {
                PointF[] pts = PolygonToPointFArray(pg, scale);
                path.AddPolygon(pts);
                pts = null;
            }
            newgraphic.FillPath(myBrush, path);
            newgraphic.DrawPath(myPen, path);
            path.Reset();
            if (rbNonZero.Checked)
            {
                path.FillMode = FillMode.Winding;
            }
            foreach (Polygon pg in clips)
            {
                PointF[] pts = PolygonToPointFArray(pg, scale);
                path.AddPolygon(pts);
                pts = null;
            }
            myPen.Color   = Color.LightSalmon;
            myBrush.Color = Color.FromArgb(16, Color.Red);
            newgraphic.FillPath(myBrush, path);
            newgraphic.DrawPath(myPen, path);

            //do the clipping ...
            if ((clips.Count > 0 || subjects.Count > 0) && !rbNone.Checked)
            {
                Polygons solution = new Polygons();
                //Stopwatch sw = new Stopwatch();
                //sw.Start();

                clipper.Clipper c = new clipper.Clipper();
                c.AddPolygons(subjects, PolyType.ptSubject);
                c.AddPolygons(clips, PolyType.ptClip);
                if (!c.Execute(GeClipType(), solution, GePolyFillType(), GePolyFillType()))
                {
                    Console.Beep(1250, 250);
                }

                //sw.Stop();
                //TimeSpan ts = sw.Elapsed;
                //this.Text = Convert.ToString(ts.TotalMilliseconds);

                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)
                {
                    solution = clipper.Clipper.OffsetPolygons(solution, (double)nudOffset.Value * scale);
                }
                foreach (Polygon pg in solution)
                {
                    PointF[] pts = PolygonToPointFArray(pg, scale);
                    if (pts.Count() > 2)
                    {
                        path.AddPolygon(pts);
                    }
                    pts = null;
                }
                myBrush.Color = Color.FromArgb(128, Color.Yellow);
                myPen.Color   = Color.Black;
                newgraphic.FillPath(myBrush, path);
                newgraphic.DrawPath(myPen, path);

                foreach (Polygon pg in solution)
                {
                    PointF[] pts = PolygonToPointFArray(pg, scale);
                    path.Reset();
                    path.AddPolygon(pts);
                }
            }
            pictureBox1.Image = mybitmap;
            newgraphic.Dispose();
            Cursor.Current = Cursors.Default;
        }
예제 #3
0
        //------------------------------------------------------------------------------
        public static Polygons OffsetPolygons(Polygons pts, double delta)
        {
            double deltaSq = delta*delta;
              Polygons result = new Polygons(pts.Count);

              for (int j = 0; j < pts.Count; ++j)
              {
            int highI = pts[j].Count -1;
            //to minimize artefacts, strip out those polygons where
            //it's shrinking and where its area < Sqr(delta) ...
            double a1 = Area(pts[j]);
            if (delta < 0) { if (a1 > 0 && a1 < deltaSq) highI = 0;}
            else if (a1 < 0 && -a1 < deltaSq) highI = 0; //nb: a hole if area < 0

            Polygon pg = new Polygon(highI*2+2);

            if (highI < 2)
            {
              result.Add(pg);
              continue;
            }

            List<DoublePoint> normals = new List<DoublePoint>(highI+1);
            normals.Add(GetUnitNormal(pts[j][highI], pts[j][0]));
            for (int i = 1; i <= highI; ++i)
              normals.Add(GetUnitNormal(pts[j][i-1], pts[j][i]));

            for (int i = 0; i < highI; ++i)
            {
              pg.Add(new IntPoint(Round(pts[j][i].X + delta *normals[i].X),
                (int)(pts[j][i].Y + delta *normals[i].Y)));
              pg.Add(new IntPoint(Round(pts[j][i].X + delta * normals[i + 1].X),
                (int)(pts[j][i].Y + delta *normals[i+1].Y)));
            }
            pg.Add(new IntPoint(Round(pts[j][highI].X + delta * normals[highI].X),
              (int)(pts[j][highI].Y + delta *normals[highI].Y)));
            pg.Add(new IntPoint(Round(pts[j][highI].X + delta * normals[0].X),
              (int)(pts[j][highI].Y + delta *normals[0].Y)));

            //round off reflex angles (ie > 180 deg) unless it's almost flat (ie < 10deg angle) ...
            //cross product normals < 0 . reflex angle; dot product normals == 1 . no angle
            if ((normals[highI].X *normals[0].Y - normals[0].X *normals[highI].Y) *delta > 0 &&
            (normals[0].X *normals[highI].X + normals[0].Y *normals[highI].Y) < 0.985)
            {
              double at1 = Math.Atan2(normals[highI].Y, normals[highI].X);
              double at2 = Math.Atan2(normals[0].Y, normals[0].X);
              if (delta > 0 && at2 < at1) at2 = at2 + Math.PI*2;
              else if (delta < 0 && at2 > at1) at2 = at2 - Math.PI*2;
              Polygon arc = BuildArc(pts[j][highI], at1, at2, delta);
              pg.InsertRange(highI * 2 + 1, arc);
            }
            for (int i = highI; i > 0; --i)
              if ((normals[i-1].X*normals[i].Y - normals[i].X*normals[i-1].Y) *delta > 0 &&
              (normals[i].X*normals[i-1].X + normals[i].Y*normals[i-1].Y) < 0.985)
              {
                double at1 = Math.Atan2(normals[i-1].Y, normals[i-1].X);
                double at2 = Math.Atan2(normals[i].Y, normals[i].X);
                if (delta > 0 && at2 < at1) at2 = at2 + Math.PI*2;
                else if (delta < 0 && at2 > at1) at2 = at2 - Math.PI*2;
                Polygon arc = BuildArc(pts[j][i-1], at1, at2, delta);
                pg.InsertRange((i - 1) * 2 + 1, arc);
              }
            result.Add(pg);
              }

              //finally, clean up untidy corners ...
              Clipper clpr = new Clipper();
              clpr.AddPolygons(result, PolyType.ptSubject);
              if (delta > 0){
            if(!clpr.Execute(ClipType.ctUnion, result, PolyFillType.pftNonZero, PolyFillType.pftNonZero))
              result.Clear();
              }
              else
              {
            IntRect r = clpr.GetBounds();
            Polygon outer = new Polygon(4);
                outer.Add(new IntPoint(r.left - 10, r.bottom + 10));
                outer.Add(new IntPoint(r.right + 10, r.bottom + 10));
                outer.Add(new IntPoint(r.right + 10, r.top - 10));
                outer.Add(new IntPoint(r.left - 10, r.top - 10));
                clpr.AddPolygon(outer, PolyType.ptSubject);
                if (clpr.Execute(ClipType.ctUnion, result, PolyFillType.pftNonZero, PolyFillType.pftNonZero))
                    result.RemoveAt(0);
                else
                    result.Clear();
              }
              return result;
        }