예제 #1
0
        private Slice GetPairs(bool outside)
        {
            Slice    s        = new Slice(this);
            PolyNode n        = polyTree.GetFirst();
            Paths    polygons = new Paths();

            while (null != n)
            {
                int      depth  = 0;
                PolyNode parent = n.Parent;
                while (parent != null)
                {
                    depth++;
                    parent = parent.Parent;
                }
                int test = (depth - 1) % 4;
                if ((outside && test < 2) || (!outside && test >= 2))
                {
                    polygons.Add(n.Contour);
                }
                n = n.GetNext();
            }

            s.polyTree = PolygonsToPolyTree(polygons);
            return(s);
        }
예제 #2
0
    private List <DelaunayTriangle> GenerateTriangles()
    {
        List <DelaunayTriangle> triangles = new List <DelaunayTriangle>();

        Dictionary <PolyNode, Polygon> dict = new Dictionary <PolyNode, Polygon>();
        PolyNode curt = m_polyTree.GetFirst();

        while (curt != null)
        {
            var polygon = Convert(curt.Contour);
            dict.Add(curt, polygon);

            if (curt.IsHole && curt.Parent != null)
            {
                dict[curt.Parent].AddHole(polygon);
            }

            curt = curt.GetNext();
        }

        foreach (var pair in dict)
        {
            var node = pair.Key;
            var poly = pair.Value;

            if (node.IsHole == false)
            {
                P2T.Triangulate(poly);
                triangles.AddRange(poly.Triangles);
            }
        }

        return(triangles);
    }
예제 #3
0
        public IEnumerable <Slice> IndividualPolygons()
        {
            PolyNode n        = polyTree.GetFirst();
            Paths    polygons = new Paths();

            while (null != n)
            {
                if (!n.IsHole && polygons.Count > 0)
                {
                    Slice s = new Slice(this);
                    s.polyTree = PolygonsToPolyTree(polygons);
                    yield return(s);

                    polygons = new Paths();
                }
                polygons.Add(n.Contour);
                n = n.GetNext();
            }
            if (polygons.Count > 0)
            {
                Slice s = new Slice(this);
                s.polyTree = PolygonsToPolyTree(polygons);
                yield return(s);
            }
        }
예제 #4
0
        public void RemoveHoles(float maxPerimiter)
        {
            Paths    keep = new Paths();
            PolyNode node = polyTree.GetFirst();

            while (node != null)
            {
                if (node.IsHole && node.ChildCount == 0)
                {
                    var   line   = LineStripFromPolygon(node.Contour);
                    float length = line.Length(LineStrip.Type.Closed);
                    if (length < maxPerimiter)
                    {
                        // Remove it
                    }
                    else
                    {
                        keep.Add(node.Contour);
                    }
                }
                else
                {
                    keep.Add(node.Contour);
                }
                node = node.GetNext();
            }
            Clipper c = new Clipper();

            c.Clear();
            c.AddPaths(keep, PolyType.ptSubject, true);
            polyTree = new PolyTree();
            c.Execute(ClipType.ctUnion, polyTree);
        }
예제 #5
0
        public virtual void GetNextPolyNodeNotEmptyTest()
        {
            PolyNode node = new PolyNode();

            node.AddChild(new PolyNode());
            node.AddChild(new PolyNode());
            NUnit.Framework.Assert.AreSame(node.Childs[0], node.GetNext());
        }
예제 #6
0
        public virtual void GetNextPolyNodeWithSiblingTest()
        {
            PolyNode node   = new PolyNode();
            PolyNode child1 = new PolyNode();
            PolyNode child2 = new PolyNode();

            node.AddChild(child1);
            node.AddChild(child2);
            NUnit.Framework.Assert.AreSame(child2, child1.GetNext());
        }
예제 #7
0
        /// <summary>
        /// Converts Clipper library
        /// <see cref="PolyTree"/>
        /// abstraction into iText
        /// <see cref="iText.Kernel.Geom.Path"/>
        /// object.
        /// </summary>
        public static Path ConvertToPath(PolyTree result)
        {
            Path     path = new Path();
            PolyNode node = result.GetFirst();

            while (node != null)
            {
                AddContour(path, node.Contour, !node.IsOpen);
                node = node.GetNext();
            }
            return(path);
        }
예제 #8
0
        private Paths PolyTreeToPolygons(PolyTree tree)
        {
            Paths    p = new Paths();
            PolyNode n = tree.GetFirst();

            while (null != n)
            {
                p.Add(n.Contour);
                n = n.GetNext();
            }
            return(p);
        }
예제 #9
0
        public IEnumerable <LineStrip> GetLines(LineType type)
        {
            PolyNode n = polyTree.GetFirst();

            while (null != n)
            {
                bool hole = n.IsHole;
                if (type == LineType.All || (hole && type == LineType.Hole) || (!hole && type == LineType.Outside))
                {
                    yield return(LineStripFromPolygon(n.Contour));
                }
                n = n.GetNext();
            }
        }
예제 #10
0
        public Slice PolygonsWithoutHoles()
        {
            Slice    s        = new Slice(this);
            PolyNode n        = polyTree.GetFirst();
            Paths    polygons = new Paths();

            while (null != n)
            {
                if (!n.IsHole && n.ChildCount == 0)
                {
                    polygons.Add(n.Contour);
                }
                n = n.GetNext();
            }

            s.polyTree = PolygonsToPolyTree(polygons);
            return(s);
        }
예제 #11
0
        /// <summary>
        /// Get all the polygons which contain holes
        /// </summary>
        /// <returns></returns>
        public Slice PolygonsWithHoles()
        {
            Slice    s        = new Slice(this);
            PolyNode n        = polyTree.GetFirst();
            Paths    polygons = new Paths();

            while (null != n)
            {
                if (n.IsHole)
                {
                    if (!polygons.Contains(n.Parent.Contour))
                    {
                        polygons.Add(n.Parent.Contour);
                    }
                    polygons.Add(n.Contour);
                }
                n = n.GetNext();
            }

            s.polyTree = PolygonsToPolyTree(polygons);
            return(s);
        }
예제 #12
0
        public virtual void GetNextNoChildsTest()
        {
            PolyNode node = new PolyNode();

            NUnit.Framework.Assert.IsNull(node.GetNext());
        }
        public List <PointF[]> Triangulate(PolyTree solution)
        {
            List <PointF[]> list = new List <PointF[]>();
            Tess            tess = new Tess();

            tess.NoEmptyPolygons = true;
            Func <IntPoint, ContourVertex> selector = delegate(IntPoint p)
            {
                ContourVertex result = default(ContourVertex);
                result.Position = new Vec3
                {
                    X = (float)p.X,
                    Y = (float)p.Y,
                    Z = 0f
                };
                return(result);
            };

            for (PolyNode polyNode = solution.GetFirst(); polyNode != null; polyNode = polyNode.GetNext())
            {
                if (!polyNode.IsOpen)
                {
                    ContourVertex[] vertices = polyNode.Contour.Select(selector).ToArray();
                    tess.AddContour(vertices);
                }
            }
            tess.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3);
            int elementCount = tess.ElementCount;

            for (int i = 0; i < elementCount; i++)
            {
                Vec3          position  = tess.Vertices[tess.Elements[i * 3 + 0]].Position;
                Vec3          position2 = tess.Vertices[tess.Elements[i * 3 + 1]].Position;
                Vec3          position3 = tess.Vertices[tess.Elements[i * 3 + 2]].Position;
                List <PointF> list2     = new List <PointF>
                {
                    new PointF(position.X, position.Y),
                    new PointF(position2.X, position2.Y),
                    new PointF(position3.X, position3.Y)
                };
                if (Math.Cross(list2[0], list2[1], list2[2]) > 0f)
                {
                    list2.Reverse();
                }
                list.Add(list2.ToArray());
            }
            return(list);
        }
예제 #14
0
        //------------------------------------------------------------------------------

        private void BmpUpdateNeeded()
        {
            const int textOffset = 20;

            if (bmpGraphics == null)
            {
                return;
            }
            FillMode fm = (mEvenOdd.Checked ? FillMode.Alternate : FillMode.Winding);

            bmpGraphics.Clear(Color.White);

            //draw the subject and clip paths ...
            Paths openPaths   = new Paths();
            Paths closedPaths = new Paths();
            Paths clipPaths   = new Paths();

            //sort the paths into open and closed subjects and (closed) clips ...
            foreach (MultiPath mp2 in allPaths)
            {
                if (mp2.RefID == CLIP)
                {
                    clipPaths.Add(mp2.Flatten());
                }
                else if (mp2.IsClosed)
                {
                    closedPaths.Add(mp2.Flatten());
                }
                else
                {
                    openPaths.Add(mp2.Flatten());
                }
            }

            DrawPath(bmpGraphics, openPaths, false, 0x0, 0xFFAAAAAA, fm, 1.0);
            DrawPath(bmpGraphics, closedPaths, true, 0x0, 0xFFAAAAAA, fm, 1.0);
            DrawPath(bmpGraphics, clipPaths, true, 0x10FF6600, 0x99FF6600, fm, 1.0);

            if (cbShowCoords.Checked)
            {
                Font       fnt   = new Font("Arial", 8);
                SolidBrush brush = new SolidBrush(Color.Navy);
                foreach (MultiPath mp2 in allPaths)
                {
                    foreach (MultiPathSegment mps in mp2)
                    {
                        foreach (IntPoint ip in mps)
                        {
                            IntPoint ip2    = new IntPoint(ip.X / scale, ip.Y / scale);
                            string   coords = ip2.X.ToString() + "," + ip2.Y.ToString();
                            bmpGraphics.DrawString(coords, fnt, brush, ip2.X - textOffset, ip2.Y - textOffset, null);
                        }
                    }
                }
                fnt.Dispose();
                brush.Dispose();
            }

            //for the active path, draw control buttons and control lines too ...
            MultiPath activePath = GetActivePath();

            if (activePath != null && activePath.Count > 0)
            {
                foreach (MultiPathSegment mps in activePath)
                {
                    CurveType pt = mps.curvetype;
                    if (pt == CurveType.CubicBezier)
                    {
                        DrawBezierCtrlLines(bmpGraphics, mps, 0xFFEEEEEE);
                    }
                    else if (pt == CurveType.QuadBezier)
                    {
                        DrawBezierCtrlLines(bmpGraphics, mps, 0xFFEEEEEE);
                    }
                }

                DrawButtons(bmpGraphics, activePath);

                //display the coords of a moving button ...
                if (MovingButtonIdx >= 0)
                {
                    Font       f  = new Font("Arial", 8);
                    SolidBrush b  = new SolidBrush(Color.Navy);
                    IntPoint   ip = MovingButtonSeg[MovingButtonIdx];
                    ip.X = (int)(ip.X / scale); ip.Y = (int)(ip.Y / scale);
                    string coords = ip.X.ToString() + "," + ip.Y.ToString();
                    bmpGraphics.DrawString(coords, f, b, ip.X - textOffset, ip.Y - textOffset, null);
                    f.Dispose();
                    b.Dispose();
                }
            }

            //if there's any clipping to be done, do it here ...
            if (!mNone.Checked && GetCurrentSubjMultiPath() != null && GetCurrentClipMultiPath() != null)
            {
                PolyFillType pft = (mEvenOdd.Checked ? PolyFillType.pftEvenOdd : PolyFillType.pftNonZero);
                ClipType     ct;
                if (mUnion.Checked)
                {
                    ct = ClipType.ctUnion;
                }
                else if (mDifference.Checked)
                {
                    ct = ClipType.ctDifference;
                }
                else if (mXor.Checked)
                {
                    ct = ClipType.ctXor;
                }
                else
                {
                    ct = ClipType.ctIntersection;
                }

                //CLIPPING DONE HERE ...
                Clipper c = new Clipper();
                c.ZFillFunction = MultiPaths.ClipCallback; //set the callback function (called at intersections)
                if (openPaths.Count > 0)
                {
                    c.AddPaths(openPaths, PolyType.ptSubject, false);
                }
                if (closedPaths.Count > 0)
                {
                    c.AddPaths(closedPaths, PolyType.ptSubject, true);
                }
                c.AddPaths(clipPaths, PolyType.ptClip, true);
                PolyTree polytree = new PolyTree();

                Paths solution;
                c.Execute(ct, polytree, pft, pft); //EXECUTE CLIP !!!!!!!!!!!!!!!!!!!!!!
                solution = Clipper.ClosedPathsFromPolyTree(polytree);
                if (!cbReconstCurve.Checked)
                {
                    DrawPath(bmpGraphics, solution, true, 0x2033AA00, 0xFF33AA00, fm, 2.0);
                }
                solution = Clipper.OpenPathsFromPolyTree(polytree);
                if (!cbReconstCurve.Checked)
                {
                    DrawPath(bmpGraphics, solution, false, 0x0, 0xFF33AA00, fm, 2.0);
                }

                //now to demonstrate reconstructing beziers & arcs ...
                if (cbReconstCurve.Checked)
                {
                    PolyNode pn = polytree.GetFirst();
                    while (pn != null)
                    {
                        if (pn.IsHole || pn.Contour.Count < 2)
                        {
                            pn = pn.GetNext();
                            continue;
                        }

                        if (pn.ChildCount > 0)
                        {
                            throw new Exception("Sorry, this demo doesn't currently handle holes");
                        }

                        //and reconstruct each curve ...
                        MultiPath reconstructedMultiPath = allPaths.Reconstruct(pn.Contour);

                        if (cbShowCtrls.Enabled && cbShowCtrls.Checked)
                        {
                            //show (small) buttons on the red reconstructed path too ...
                            DrawButtons(bmpGraphics, reconstructedMultiPath, true);
                        }

                        //now to show how accurate these reconstructed (control) paths are,
                        //we flatten them (drawing them red) so we can compare them with
                        //the original flattened paths (light gray) ...
                        Paths paths = new Paths();
                        paths.Add(reconstructedMultiPath.Flatten());
                        DrawPath(bmpGraphics, paths, !pn.IsOpen, 0x18FF0000, 0xFFFF0000, fm, 2.0);

                        pn = pn.GetNext();
                    }
                }
                //else //shows just how many vertices there are in flattened paths ...
                //{
                //  solution = Clipper.PolyTreeToPaths(polytree);
                //  MultiPath flatMultiPath = new MultiPath(null, 0, false);
                //  foreach (Path p in solution)
                //    flatMultiPath.NewMultiPathSegment(PathType.Line, p);
                //  DrawButtons(bmpGraphics, flatMultiPath, true);
                //}
            }

            string s = "  ";

            if (mIntersection.Checked)
            {
                s += "INTERSECTION";
            }
            else if (mUnion.Checked)
            {
                s += "UNION";
            }
            else if (mDifference.Checked)
            {
                s += "DIFFERENCE";
            }
            else if (mXor.Checked)
            {
                s += "XOR";
            }
            else
            {
                s += "NO CLIPPING";
            }
            s += " with ";
            if (mEvenOdd.Checked)
            {
                s += "EVENODD fill.";
            }
            else
            {
                s += "NONZERO fill.";
            }
            toolStripStatusLabel2.Text = s;
            displayPanel.Invalidate();
        }
예제 #15
0
        /// <summary>
        /// Get a list of triangles which will fill the area described by the slice
        /// </summary>
        public IEnumerable <Triangle> Triangles()
        {
            TriangleNet.Behavior behavior = new TriangleNet.Behavior();
            behavior.ConformingDelaunay = true;

            foreach (var poly in IndividualPolygons())
            {
                PolyNode      node     = polyTree.GetFirst();
                InputGeometry geometry = new InputGeometry();
                while (node != null)
                {
                    var offset = geometry.Points.Count();
                    var index  = 0;
                    foreach (IntPoint point in node.Contour)
                    {
                        geometry.AddPoint(point.X, point.Y);
                        if (index > 0)
                        {
                            geometry.AddSegment(index - 1 + offset, index + offset);
                        }
                        index++;
                    }
                    geometry.AddSegment(index - 1 + offset, offset);

                    if (node.IsHole)
                    {
                        // To describe a hole, AddHole must be called with a location inside the hole.
                        IntPoint last         = new IntPoint(0, 0);
                        bool     lastKnown    = false;
                        double   longest      = 0;
                        IntPoint longestAlong = new IntPoint(0, 0);
                        IntPoint from         = new IntPoint(0, 0);
                        foreach (IntPoint point in node.Contour)
                        {
                            if (lastKnown)
                            {
                                IntPoint along  = new IntPoint(point.X - last.X, point.Y - last.Y);
                                double   length = Math.Sqrt(along.X * along.X + along.Y * along.Y);
                                if (length > longest)
                                {
                                    longest      = length;
                                    longestAlong = along;
                                    from         = last;
                                }
                            }
                            last      = point;
                            lastKnown = true;
                        }
                        if (longest > 0)
                        {
                            double perpendicularX = ((double)longestAlong.Y * (double)scale * 0.001d) / longest;
                            double perpendicularY = -((double)longestAlong.X * (double)scale * 0.001d) / longest;
                            geometry.AddHole(perpendicularX + from.X + longestAlong.X / 2.0d,
                                             perpendicularY + from.Y + longestAlong.Y / 2.0d);
                        }
                        else
                        {
                        }
                    }
                    node = node.GetNext();
                }

                if (geometry.Points.Count() > 0)
                {
                    var mesh = new TriangleNet.Mesh(behavior);
                    mesh.Triangulate(geometry);
                    mesh.Renumber();
                    foreach (Triangle t in this.GetMeshTriangles(mesh))
                    {
                        yield return(t);
                    }
                }
            }
        }