Exemplo n.º 1
0
        // polygons treatment
        private Polygons getPolygonsInRegion(int i, int j, double delta)
        {
            //converting the boundingbox of the region to a polygon
            Polygon clip = this.BoundingBoxToPolygon(this.ReagionsBoundingBoxes[i, j]);
            //initial polygons denote part of the subregions that are located within the region
            Polygons initialPolygons = new Polygons();
            Clipper  c = new Clipper();

            //c.StrictlySimple = true; // jeremy
            c.AddPolygons(this.IntRoads, PolyType.ptSubject);
            c.AddPolygon(clip, PolyType.ptClip);
            c.Execute(ClipType.ctIntersection, initialPolygons, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);
            // negative Clip is the roads inside the region clipping the region
            Polygons negativeClip = new Polygons();
            Clipper  negative     = new Clipper();

            //negative.StrictlySimple = true; // jeremy
            negative.AddPolygons(initialPolygons, PolyType.ptClip);
            negative.AddPolygon(clip, PolyType.ptSubject);
            negative.Execute(ClipType.ctIntersection, negativeClip, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);
            //shrinking the negative clip to remove common edges
            Polygons negativeShrank = Clipper.OffsetPolygons(negativeClip, -1 * Math.Pow(10, this.Exponent - 1), ClipperLib.JoinType.jtMiter);
            // expanding the negative shrink the negative clip to remove common edges
            Polygons negativeShrankExpand         = Clipper.OffsetPolygons(negativeShrank, Math.Pow(10, this.Exponent - 1) + 3, ClipperLib.JoinType.jtMiter);
            Polygons negativeShrankExpandNegative = new Polygons();
            Clipper  negativeAgain = new Clipper();

            //negativeAgain.StrictlySimple = true; // jeremy
            negativeAgain.AddPolygons(negativeShrankExpand, PolyType.ptSubject);
            negativeAgain.AddPolygon(clip, PolyType.ptClip);
            negativeAgain.Execute(ClipType.ctIntersection, negativeShrankExpandNegative, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

            return(negativeShrankExpandNegative);
        }
Exemplo n.º 2
0
    public List <IntPoint> AroundWall(Vector2 containPoint, float offset)
    {
        //将相邻的障碍物轮廓合并在一起
        List <List <IntPoint> > unions = new List <List <IntPoint> >();
        Clipper clipper = new Clipper();

        for (int i = 0; i < m_walls.Count; i++)
        {
            clipper.AddPolygons(m_walls[i].m_polygons, PolyType.ptSubject);
        }

        if (!clipper.Execute(ClipType.ctUnion, unions))
        {
            Debug.LogError("无法合并顶点");
            return(null);
        }

        //过滤出特定的那个轮廓
        List <IntPoint> contour = null;

        for (int i = 0; i < unions.Count; i++)
        {
            if (ClipperUtils.IsPointOnPolygonEdge(containPoint, unions[i]))
            {
                contour = unions[i];
                break;
            }
        }
        if (contour == null)
        {
            Debug.LogError("没找到包含特定点的障碍轮廓");
            return(null);
        }

        //对轮廓进行偏移
        List <List <IntPoint> > result = new List <List <IntPoint> >()
        {
            contour
        };

        result = Clipper.OffsetPolygons(result, offset * ClipperUtils.k_precision);
        if (result.Count > 1)
        {
            Debug.LogError("轮廓偏移后产生多个轮廓了?");
            return(result[0]);
        }
        else if (result.Count == 0)
        {
            Debug.LogError("轮廓偏移后不产生轮廓了?");
            return(null);
        }
        else
        {
            return(result[0]);
        }
    }
Exemplo n.º 3
0
        public Paths BuildOutlines(float growamt = 5 *3)
        {
            ClipperLib.Clipper cp = new ClipperLib.Clipper();
            Path pp = new Path();

            pp.AddRange(Vertices);
            Paths pps = new Paths();

            pps.Add(pp);
            var Res = Clipper.OffsetPolygons(pps, growamt, JoinType.jtRound);


            return(Res);
        }
Exemplo n.º 4
0
        public void  ShrinkFromShape(Path shape, float amt = 7 *3)
        {
            Path pp = new Path();

            pp.AddRange(shape);
            Paths pps = new Paths();

            pps.Add(pp);
            var Res = Clipper.OffsetPolygons(pps, -amt);

            if (Res.Count == 1)
            {
                Vertices.Clear();
                Vertices.AddRange(Res[0]);
            }
        }
Exemplo n.º 5
0
        internal List <PolyLine> Offset(double margin, int v)
        {
            List <PolyLine> Res = new List <PolyLine>();


            Polygons clips = new Polygons();
            Polygon  b     = this.toPolygon();

            clips.Add(b);
            Polygons clips2 = Clipper.OffsetPolygons(clips, margin * 100000.0f, JoinType.jtRound);

            foreach (var r in clips2)
            {
                PolyLine PLR = new PolyLine(v++);
                PLR.fromPolygon(r);
                Res.Add(PLR);
            }


            return(Res);
        }
Exemplo n.º 6
0
        public string MinimalDXFSave(string outputfile, double offset = 3.0, double holediameter = 3.2)
        {
            if (Directory.Exists(outputfile))
            {
                outputfile = Path.Combine(outputfile, "SickOfBeige");
            }

            PolyLine      Biggest     = null;
            double        BiggestArea = 0;
            List <PointD> Holes       = new List <PointD>();
            var           holeradius  = holediameter / 2.0;


            double Circumference = 2 * Math.PI * holeradius;

            foreach (var a in PLSs.Where(x => x.Layer == BoardLayer.Outline))
            {
                foreach (var b in a.OutlineShapes)
                {
                    var    A      = b.toPolygon();
                    double LRatio = (b.OutlineLength() / Circumference);
                    double Lperc  = Math.Abs(LRatio - 1);
                    if (Lperc < 0.1)
                    {
                        if (b.Vertices.Count > 5)
                        {
                            var  C     = b.GetCentroid();
                            bool round = true;
                            foreach (var v in b.Vertices)
                            {
                                var L = (C - v).Length();
                                if (Math.Abs(L - holeradius) > 0.2)
                                {
                                    // not very round!
                                    round = false;
                                }
                            }
                            if (round)
                            {
                                Console.WriteLine("Hole detected in outline:{0} {1} {2} {3} {4} {5}", a.Layer, a.Side, C, LRatio, Lperc, b.Vertices.Count);
                                Holes.Add(C);
                            }
                        }
                        // might be hole!
                    }
                    var Area = Clipper.Area(A);
                    if (Area > BiggestArea)
                    {
                        Biggest     = b;
                        BiggestArea = Area;
                    }
                }
            }

            Polygons Offsetted = new Polygons();

            List <String> Lines = new List <string>();

            Lines.Add("0");
            Lines.Add("SECTION");
            Lines.Add("2 ");
            Lines.Add("ENTITIES");


            if (Biggest != null)
            {
                Polygons clips = new Polygons();
                clips.Add(Biggest.toPolygon());
                Offsetted = Clipper.OffsetPolygons(clips, offset * 100000.0f, JoinType.jtRound);
                foreach (var poly in Offsetted)
                {
                    PolyLine P = new PolyLine(PolyLine.PolyIDs.Temp);

                    P.fromPolygon(poly);

                    for (int i = 0; i < P.Vertices.Count; i++)
                    {
                        var V1 = P.Vertices[i];
                        var V2 = P.Vertices[(i + 1) % P.Vertices.Count];

                        Lines.Add("0");
                        Lines.Add("LINE");
                        Lines.Add("8");
                        Lines.Add("Outline");
                        Lines.Add("10");
                        Lines.Add(V1.X.ToString().Replace(',', '.'));
                        Lines.Add("20");
                        Lines.Add(V1.Y.ToString().Replace(',', '.'));
                        Lines.Add("11");
                        Lines.Add(V2.X.ToString().Replace(',', '.'));
                        Lines.Add("21");
                        Lines.Add(V2.Y.ToString().Replace(',', '.'));
                    }
                }
            }
            else
            {
                Errors.Add("No longest outline found - not generating offset curve");
            }

            foreach (var a in Excellons)
            {
                foreach (var t in a.Tools)
                {
                    var R = t.Value.Radius;
                    if (Math.Abs(R * 2 - holediameter) < 0.05)
                    {
                        foreach (var h in t.Value.Drills)
                        {
                            Holes.Add(h);
                        }
                    }
                }
            }


            foreach (var a in Holes)
            {
                for (int i = 0; i < 40; i++)
                {
                    double P  = i * Math.PI * 2.0 / 40.0;
                    double P2 = (i + 1) * Math.PI * 2.0 / 40.0;
                    var    C1 = Math.Cos(P) * holeradius;
                    var    C2 = Math.Cos(P2) * holeradius;
                    var    S1 = Math.Sin(P) * holeradius;
                    var    S2 = Math.Sin(P2) * holeradius;
                    double x1 = a.X + C1;
                    double y1 = a.Y + S1;
                    double x2 = a.X + C2;
                    double y2 = a.Y + S2;

                    Lines.Add("0");
                    Lines.Add("LINE");
                    Lines.Add("8");
                    Lines.Add("Holes");
                    Lines.Add("10");
                    Lines.Add(x1.ToString().Replace(',', '.'));
                    Lines.Add("20");
                    Lines.Add(y1.ToString().Replace(',', '.'));
                    Lines.Add("11");
                    Lines.Add(x2.ToString().Replace(',', '.'));
                    Lines.Add("21");
                    Lines.Add(y2.ToString().Replace(',', '.'));
                }
            }

            Lines.Add("0");
            Lines.Add("ENDSEC");
            Lines.Add("0");
            Lines.Add("EOF");
            File.WriteAllLines(outputfile + ".dxf", Lines);
            float scalefac = 10;

            Console.WriteLine("Report: {0} holes created in case ({1} spacers and {1} screws needed!)", Holes.Count, Holes.Count * 2);
            {
                var BB = new GerberLibrary.Bounds();
                BB.AddPolygons(Offsetted);
                BB.AddPolyLine(Biggest);

                Bitmap   B = new Bitmap((int)((BB.Width()) * scalefac) + 6, (int)((BB.Height()) * scalefac) + 6);
                Graphics G = Graphics.FromImage(B);
                G.Clear(Color.Transparent);
                G.Clear(Color.White);

                G.TranslateTransform(3, 3);
                G.ScaleTransform(scalefac, scalefac);
                G.TranslateTransform((float)-(BB.TopLeft.X), (float)-(BB.TopLeft.Y));
                Pen pen  = new Pen(Color.Black, 0.1f);
                Pen pen2 = new Pen(Color.FromArgb(160, 160, 160), 0.1f);
                pen2.DashPattern = new float[2] {
                    2, 2
                };
                GerberImageCreator.ApplyAASettings(G);
                RectangleF R = new RectangleF(0, 0, (float)holediameter, (float)holediameter);

                foreach (var a in Holes)
                {
                    R.X = (float)a.X - (float)holeradius;
                    R.Y = (float)a.Y - (float)holeradius;
                    G.DrawEllipse(pen, R);
                }

                foreach (var poly in Offsetted)
                {
                    PolyLine Pl = new PolyLine(PolyLine.PolyIDs.Temp);

                    Pl.fromPolygon(poly);
                    var Points = new List <PointF>(Pl.Vertices.Count);
                    for (int i = 0; i < Pl.Vertices.Count; i++)
                    {
                        Points.Add(Pl.Vertices[i].ToF());
                    }
                    Points.Add(Pl.Vertices[0].ToF());
                    G.DrawLines(pen, Points.ToArray());
                }

                {
                    PolyLine Pl = Biggest;

                    var Points = new List <PointF>(Pl.Vertices.Count);

                    for (int i = 0; i < Pl.Vertices.Count; i++)
                    {
                        Points.Add(Pl.Vertices[i].ToF());
                    }

                    Points.Add(Pl.Vertices[0].ToF());
                    G.DrawLines(pen2, Points.ToArray());
                }

                var ImagePNG = outputfile + ".png";
                B.Save(ImagePNG);
                return(ImagePNG);
            }
        }
Exemplo n.º 7
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.White);

            GraphicsPath path = new GraphicsPath();

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

            //draw subjects ...
            foreach (Polygon pg in subjects)
            {
                PointF[] pts = PolygonToPointFArray(pg, scale);
                path.AddPolygon(pts);
                pts = null;
            }
            Pen        myPen   = new Pen(Color.FromArgb(196, 0xC3, 0xC9, 0xCF), (float)0.6);
            SolidBrush myBrush = new SolidBrush(Color.FromArgb(127, 0xDD, 0xDD, 0xF0));

            newgraphic.FillPath(myBrush, path);
            newgraphic.DrawPath(myPen, path);
            path.Reset();

            //draw clips ...
            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.FromArgb(196, 0xF9, 0xBE, 0xA6);
            myBrush.Color = Color.FromArgb(127, 0xFF, 0xE0, 0xE0);
            newgraphic.FillPath(myBrush, path);
            newgraphic.DrawPath(myPen, path);

            //do the clipping ...
            if ((clips.Count > 0 || subjects.Count > 0) && !rbNone.Checked)
            {
                Polygons solution2 = new Polygons();
                Clipper  c         = new Clipper();
                c.AddPolygons(subjects, PolyType.ptSubject);
                c.AddPolygons(clips, PolyType.ptClip);
                exSolution.Clear();
                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)
                    {
                        solution2 = Clipper.OffsetPolygons(solution, (double)nudOffset.Value * scale, JoinType.jtMiter);
                    }
                    else
                    {
                        solution2 = new Polygons(solution);
                    }
                    foreach (Polygon pg in solution2)
                    {
                        PointF[] pts = PolygonToPointFArray(pg, scale);
                        if (pts.Count() > 2)
                        {
                            path.AddPolygon(pts);
                        }
                        pts = null;
                    }
                    myBrush.Color = Color.FromArgb(127, 0x66, 0xEF, 0x7F);
                    myPen.Color   = Color.FromArgb(255, 0, 0x33, 0);
                    myPen.Width   = 1.0f;
                    newgraphic.FillPath(myBrush, path);
                    newgraphic.DrawPath(myPen, path);

                    //now do some fancy testing ...
                    Font       f = new Font("Arial", 8);
                    SolidBrush b = new SolidBrush(Color.Navy);
                    double     subj_area = 0, clip_area = 0, int_area = 0, union_area = 0;
                    c.Clear();
                    c.AddPolygons(subjects, PolyType.ptSubject);
                    c.Execute(ClipType.ctUnion, solution2, GetPolyFillType(), GetPolyFillType());
                    foreach (Polygon pg in solution2)
                    {
                        subj_area += Clipper.Area(pg);
                    }
                    c.Clear();
                    c.AddPolygons(clips, PolyType.ptClip);
                    c.Execute(ClipType.ctUnion, solution2, GetPolyFillType(), GetPolyFillType());
                    foreach (Polygon pg in solution2)
                    {
                        clip_area += Clipper.Area(pg);
                    }
                    c.AddPolygons(subjects, PolyType.ptSubject);
                    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;
                    Rectangle rec = new Rectangle(pictureBox1.ClientSize.Width - 108,
                                                  pictureBox1.ClientSize.Height - 116, 104, 106);
                    newgraphic.FillRectangle(new SolidBrush(Color.FromArgb(196, Color.WhiteSmoke)), rec);
                    newgraphic.DrawRectangle(myPen, rec);
                    rec.Inflate(new Size(-2, 0));
                    newgraphic.DrawString("Areas", f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 14));
                    newgraphic.DrawString("subj: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString((subj_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 12));
                    newgraphic.DrawString("clip: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString((clip_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 12));
                    newgraphic.DrawString("intersect: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString((int_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 12));
                    newgraphic.DrawString("---------", f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 10));
                    newgraphic.DrawString("s + c - i: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString(((subj_area + clip_area - int_area) / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 10));
                    newgraphic.DrawString("---------", f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 10));
                    newgraphic.DrawString("union: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString((union_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 10));
                    newgraphic.DrawString("---------", f, b, rec, rtStringFormat);
                } //end if succeeded
            }     //end if something to clip

            pictureBox1.Image = mybitmap;
            newgraphic.Dispose();
            Cursor.Current = Cursors.Default;
        }
Exemplo n.º 8
0
        public void redraw()
        {
            canvas.Children.Clear();

            if (rooms.Count == 0 && decoration.Count == 0)
            {
                return;
            }

            c.Clear();
            Polygons outline = new Polygons();

            c.AddPolygons(rooms, PolyType.ptSubject);
            c.AddPolygons(decoration, PolyType.ptSubject);
            c.Execute(ClipType.ctUnion, outline, PolyFillType.pftNonZero, PolyFillType.pftNonZero);
            outline = Clipper.OffsetPolygons(outline, 10, JoinType.jtMiter);

            // Bevel inside corners of the outline
            foreach (Polygon p in outline)
            {
                // Skip holes
                if (!Clipper.Orientation(p))
                {
                    continue;
                }

                // Find the inside corners
                List <bool> corners = new List <bool>();
                for (int j = 0; j < p.Count; ++j)
                {
                    int i = (j + p.Count - 1) % p.Count;
                    int k = (j + 1) % p.Count;

                    IntPoint e1 = new IntPoint(p[j].X - p[i].X, p[j].Y - p[i].Y);
                    IntPoint e2 = new IntPoint(p[j].X - p[k].X, p[j].Y - p[k].Y);

                    int a = (int)(e1.X * e2.Y - e2.X * e1.Y);

                    corners.Add(a > 0);
                }

                // Bevel them to the midpoints of the original lines
                for (int j = 0; j < p.Count; ++j)
                {
                    int i = (j + p.Count - 1) % p.Count;
                    int k = (j + 1) % p.Count;

                    if (corners[j])
                    {
                        if (!corners[i])
                        {
                            corners.Insert(j, true);
                            p.Insert(j, new IntPoint((p[i].X + p[j].X) / 2, (p[i].Y + p[j].Y) / 2));

                            ++j; ++k;
                        }

                        p[j] = new IntPoint((p[j].X + p[k].X) / 2, (p[j].Y + p[k].Y) / 2);
                    }
                }
            }

            foreach (Polygon p in rooms)
            {
                canvas.Children.Add(ToSystemPolygon(p));
            }

            foreach (Polygon p in outline)
            {
                canvas.Children.Add(ToSystemPolygon(p, Brushes.Yellow));
            }

            UpdateLayout();
        }
Exemplo n.º 9
0
        private static unsafe bool ApplyFog(Bitmap fog, int delta, params FogUpdate[] fogUpdates)
        {
            if (fog == null || fogUpdates == null || !fogUpdates.Any())
            {
                return(false);
            }

            var isInwards = (delta < 0);

            var anyComplete = false;

            // TODO: Look into a better way to handle multiple fog updates at the same time?
            foreach (var fogUpdate in fogUpdates)
            {
                var points      = fogUpdate.Points;
                var isAddingFog = !fogUpdate.IsClearing;

                var pointPolygon  = new List <IntPoint>(points.Select(x => new IntPoint(x.X, x.Y)));
                var pointPolygons = new List <List <IntPoint> >()
                {
                    pointPolygon
                };
                var offsetPolygons = Clipper.OffsetPolygons(pointPolygons, delta, JoinType.jtRound);

                // If our offset was simply too large to have an offset polygon, we'll change it (towards 0)
                // until we find one. If we never do, we'll just do direct drawing as the shape is too small for alpha fading.
                var retryDelta = delta;
                if (isInwards)
                {
                    // Inwards means the delta is negative (to make the fog go inwards), so we'll add to it to get it to -1.
                    while (offsetPolygons.Count == 0 && retryDelta != -1)
                    {
                        // The last iteration will end up with retryDelta set to 1, which will cause the smallest offset polygon to be generated.
                        retryDelta     = Math.Min(-1, retryDelta + DnDMapConstants.FogAlphaEffectRetryDelta);
                        offsetPolygons = Clipper.OffsetPolygons(pointPolygons, retryDelta, JoinType.jtRound);
                    }
                }

                // If we still don't have any offset polygon, then the size must just be too small so we'll draw it using the direct method instead.
                if (offsetPolygons.Count == 0)
                {
                    anyComplete |= ApplyFogDirect(fog, fogUpdates);
                    continue;
                }

                var offsetPoints = offsetPolygons[0].Select(x => new SimplePoint((int)x.X, (int)x.Y)).ToArray();

                // When we're doing inwards delta, the offsetPoints shape is smaller than the points shape.
                // Therefore, we'll flip the variables to pretend that the user drew the smaller shape.
                if (isInwards)
                {
                    var p = points;
                    points       = offsetPoints;
                    offsetPoints = p;
                }

                var boundingBoxBuffered = GetBoundingBox(fog, offsetPoints, 4);
                var boundingBox         = GetBoundingBox(fog, points, 0);

                var bmd       = fog.LockBits(boundingBoxBuffered, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
                int pixelSize = 4;
                Parallel.For(0, bmd.Height, (y) =>
                {
                    var row = (byte *)bmd.Scan0 + (y * bmd.Stride);
                    for (var x = 0; x < bmd.Width; x++)
                    {
                        var offsetX = x + boundingBoxBuffered.X;
                        var offsetY = y + boundingBoxBuffered.Y;

                        if (isAddingFog)
                        {
                            // If the pixel is already opaque, then we'll skip it
                            if (row[x * pixelSize + 3] == 255)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            // If the pixel is already transparent, then we'll hide it
                            if (row[x * pixelSize + 3] == 0)
                            {
                                continue;
                            }
                        }

                        // When going outwards, we reveal everything in the points (the actual drawn polygon)
                        //                      we partially reveal anything in the offset polygons
                        // When going inwards, we reveal anythign in the offset points (an inner polygon)
                        //                      we partially reveal anything in the actual polygon
                        // This is handled by flipping the points and offsetPoints variables above.
                        if (IsPointInPolygon(points, offsetX, offsetY))
                        {
                            row[x * pixelSize + 3] = (byte)(isAddingFog ? 255 : 0);
                        }
                        else if (IsPointInPolygon(offsetPoints, offsetX, offsetY))
                        {
                            var testPoint = new SimplePoint(offsetX, offsetY);
                            var dist      = LineToPointDistance2D(points[0], points[1], testPoint);
                            for (int i = 0, j = points.Length - 1; i < points.Length; j = i++)
                            {
                                var newDist = LineToPointDistance2D(points[j], points[i], testPoint);
                                if (newDist < dist)
                                {
                                    dist = newDist;
                                }
                            }

                            var alpha = (255 - 5.5 * dist);
                            alpha     = Math.Max(Math.Floor(alpha), 0);
                            if (isAddingFog)
                            {
                                alpha = Math.Min(alpha + row[x * pixelSize + 3], 255);
                            }
                            else
                            {
                                alpha = Math.Max(row[x * pixelSize + 3] - alpha, 0);
                            }
                            row[x * pixelSize + 3] = (byte)(alpha);
                        }
                    }
                });

                fog.UnlockBits(bmd);
                anyComplete = true;
            }

            return(anyComplete);
        }