Example #1
0
 public void InsertLoop(LineLoop l)
 {
     if (!AnyIntersects(l) && !ContainsLoop(l))
     {
         PolygonNode        lowestEnclosingLoop   = FindLowestNodeEnclosing(l);
         List <PolygonNode> highestEnclosedByLoop = FindHighestNodeEnclosedBy(l);
         if (lowestEnclosingLoop == null)
         {
             nodes.Add(new PolygonNode(l, null));
         }
         else
         {
             lowestEnclosingLoop.children.Add(new PolygonNode(l, lowestEnclosingLoop));
         }
         if (highestEnclosedByLoop != null)
         {
             foreach (PolygonNode n in highestEnclosedByLoop)
             {
                 n.ChangeParent(null);
             }
         }
     }
     else
     {
         throw new Exception("Loop to be added intersects pre-existing loops");
     }
 }
Example #2
0
        private List <PolygonNode> FindHighestNodeEnclosedBy(LineLoop l)
        {
            List <PolygonNode> found = new List <PolygonNode>();

            foreach (PolygonNode n in nodes)
            {
                if (n.loop.IsInsideOther(l))
                {
                    found.Add(n);
                }
            }
            if (found.Count != 0)
            {
                return(found);
            }
            else
            {
                foreach (PolygonNode n in nodes)
                {
                    found = n.FindHighestNodeEnclosedBy(l);
                    if (found != null)
                    {
                        return(found);
                    }
                }
                return(null);
            }
        }
Example #3
0
        public static IntersectionResolution GetIntersectionInfo(WeaklySimplePolygon lhs, WeaklySimplePolygon rhs)
        {
            IntersectionResolution res = new IntersectionResolution {
                intersections = new List <IntersectionPair>(),
                lhs           = new Dictionary <int, List <int> >(),
                rhs           = new Dictionary <int, List <int> >()
            };

            //-1 just refers to verts and not an index into holes
            for (int i = -1; i < lhs.holes.Count; i++)
            {
                LineLoop lhsLoop = (i == -1) ? lhs.verts : lhs.holes[i];
                for (int j = -1; j < rhs.holes.Count; j++)
                {
                    LineLoop rhsLoop = (j == -1) ? rhs.verts : rhs.holes[j];
                    List <LineLoop.LoopLoopIntersection> theseIntersections = LineLoop.AllIntersections(lhsLoop, rhsLoop);

                    foreach (LineLoop.LoopLoopIntersection info in theseIntersections)
                    {
                        gvec2 lhsDir = lhsLoop[info.lhsIndex + 1] - lhsLoop[info.lhsIndex];
                        gvec2 rhsDir = rhsLoop[info.rhsIndex + 1] - rhsLoop[info.rhsIndex];

                        TraversalMode lhsMode = gvec2.Dot(lhsDir, rhsDir.RotatedCCW90()) > 0 ? TraversalMode.entering : TraversalMode.exiting;
                        TraversalMode rhsMode = gvec2.Dot(rhsDir, lhsDir.RotatedCCW90()) > 0 ? TraversalMode.entering : TraversalMode.exiting;

                        res.intersections.Add(new IntersectionPair {
                            vert = info.position,
                            lhs  = new IntersectionInfo {
                                index   = i,
                                segment = info.lhsIndex,
                                param   = info.lhsParam,
                                mode    = lhsMode
                            },
                            rhs = new IntersectionInfo {
                                index   = j,
                                segment = info.rhsIndex,
                                param   = info.rhsParam,
                                mode    = rhsMode
                            }
                        });

                        if (!res.lhs.ContainsKey(i))
                        {
                            res.lhs[i] = new List <int>();
                        }
                        res.lhs[i].Add(res.intersections.Count - 1);
                        if (!res.rhs.ContainsKey(j))
                        {
                            res.rhs[j] = new List <int>();
                        }
                        res.rhs[j].Add(res.intersections.Count - 1);
                    }
                }
            }

            return(res);
        }
        public void SplitLinesIntoLine()
        {
            //seriesofwords
            string[] lines       = { "No Comment", "Not Required" };
            string   line        = lines[0];
            string   actualLine1 = LineLoop.ApplyLineLoop(lines, 0);

            Assert.True(line == actualLine1);
        }
Example #5
0
 public bool ContainsLoop(LineLoop l)
 {
     foreach (PolygonNode n in nodes)
     {
         if (n.ContainsLoop(l))
         {
             return(true);
         }
     }
     return(false);
 }
Example #6
0
 public bool AnyIntersects(LineLoop l)
 {
     foreach (PolygonNode n in nodes)
     {
         if (n.AnyIntersects(l))
         {
             return(true);
         }
     }
     return(false);
 }
Example #7
0
 private PolygonNode FindLowestNodeEnclosing(LineLoop l)
 {
     foreach (PolygonNode n in nodes)
     {
         PolygonNode lowest = n.FindLowestNodeEnclosing(l);
         if (lowest != null)
         {
             return(lowest);
         }
     }
     return(null);
 }
Example #8
0
 public bool ContainsLoop(LineLoop l)
 {
     if (loop == l)
     {
         return(true);
     }
     foreach (PolygonNode n in children)
     {
         if (n.ContainsLoop(l))
         {
             return(true);
         }
     }
     return(false);
 }
Example #9
0
 public bool AnyIntersects(LineLoop l)
 {
     if (l.IntersectsOther(loop))
     {
         return(true);
     }
     else
     {
         foreach (PolygonNode n in children)
         {
             if (n.AnyIntersects(l))
             {
                 return(true);
             }
         }
         return(false);
     }
 }
Example #10
0
 public PolygonNode FindLowestNodeEnclosing(LineLoop l)
 {
     if (l.IsInsideOther(loop))
     {
         foreach (PolygonNode n in children)
         {
             PolygonNode lowest = n.FindLowestNodeEnclosing(l);
             if (lowest != null)
             {
                 return(lowest);
             }
         }
         return(this);
     }
     else
     {
         return(null);
     }
 }
Example #11
0
            /// <summary>
            /// Combine one line loop with another
            /// </summary>
            /// <param name="other"></param>
            /// <returns>Array of LineLoops which don't intersect (will be one or two loops)</returns>
            public static LineLoop Intersect(LineLoop one, LineLoop another, Vector3 normal)
            {
                LineStrip one2 = new LineStrip();
                List<Vector3> vv = new List<Vector3>(one.Vertices);
                for (int i = 0; i < vv.Count; i++)
                {
                    int j = (i + 2) % vv.Count;
                    one2.Append(vv[j]);
                }
                one2.Append(one2.GetVertex(0));
                one = new LineLoop(one2);

                GL.PointSize(19);
                GL.Color3(Color.GreenYellow);
                GL.Begin(BeginMode.Points);
                GL.Vertex3(one.GetVertex(0));
                GL.End();
                GL.PointSize(1);

                LineLoop following = one;
                LineLoop searching = another;

                Vector3 startPoint = following.GetVertex(0);
                LineStrip ls = new LineStrip();
                List<LineLoop> loops = new List<LineLoop>();
                for (int i = 0; i < following.indices.Count(); i++)
                {
                    Vector3 v1 = following.GetVertex(i);
                    Vector3 v2 = following.GetVertex((i + 1) % following.indices.Count());

                    //if (ls.ContainsVertex(v1))
                   // {
                        bool matched = false;
                        LineStrip ls2 = new LineStrip();
                        foreach (Vector3 v in ls.Vertices)
                        {
                            if (!matched && (v - v1).Length < 0.001)
                            {
                                matched = true;
                            }
                            if (matched)
                            {
                                ls2.Append(v);
                            }
                        }
                        if (matched)
                        {

                            ls2.Append(v1);
                            GL.PushMatrix();
                            GL.Translate(0, 0, 50);
                            ls2.Draw();
                            GL.PopMatrix();
                            // Done!  Got a loop
                            LineLoop l = new LineLoop(ls2);
                            return l;
                        }
                    //}
                    ls.Append(v1);

                    int searchingCount = searching.indices.Count();
                    for (int j = 0; j < searchingCount; j++)
                    {
                        Vector3 v3 = searching.GetVertex(j);
                        Vector3 v4 = searching.GetVertex((j + 1) % searchingCount);

                        Vector3 n1 = (v2 - v1);
                        Vector3 n2 = (v4 - v3);

                        n1.Normalize();
                        n2.Normalize();

                        float d1 = DistanceToCylinder(v1, v2, v3);
                        float d2 = DistanceToCylinder(v3, v4, v1);

                        if (d2 < 10)
                        {
                        }

                        // Point v3 is on Line v1-v2:
                        if (DistanceToCylinder(v1, v2, v3) < 1)
                        {
                            // Follow the line most to the outside
                            float angle = Angle(n1, n2, normal);
                            if (angle < OpenTK.MathHelper.Pi)
                            {
                                GL.PointSize(10);
                                GL.Color3(Color.Orange);
                                GL.Begin(BeginMode.Points);
                                GL.Vertex3(v3);
                                GL.End();
                                GL.PointSize(1);
                                ls.Append(v3);
                                // Follow the line v3-v4
                                LineLoop temp = searching;
                                searching = following;
                                following = temp;
                                i = j;
                                break;
                            }
                            else
                            {
                                // Continue following the line v1-v2
                            }
                        }
                        // Point v2 is on the line v3-v4
                        else if (DistanceToCylinder(v3, v4, v1) < 1)
                        {
                            // Follow the line most to the outside
                            float angle = Angle(n1, n2, normal);
                            if (angle < OpenTK.MathHelper.Pi)
                            {
                                GL.PointSize(10);
                                GL.Color3(Color.Orange);
                                GL.Begin(BeginMode.Points);
                                GL.Vertex3(v1);
                                GL.End();
                                GL.PointSize(1);
                                //ls.Append(v1);
                                // Follow the line v3-v4
                                LineLoop temp = searching;
                                searching = following;
                                following = temp;
                                i = j;
                                break;
                            }
                            else
                            {
                                // Continue following the line v1-v2
                            }
                        }
                        // TODO: Add case for intersecting lines!
                        //else if (0)
                        //{
                        //}
                    }

                }
                //return loops.ToArray();

                ls.Append(following.GetVertex(following.indices[0]));
                //if (ls.ContainsVertex(v1))
                //{
                    //ls.Append(v1);
                    GL.PushMatrix();
                    GL.Translate(0, 0, 50);
                    ls.Draw();
                    GL.PopMatrix();
                    // Done!  Got a loop
                    LineLoop l2 = new LineLoop(ls);
                    return l2;
                //}
            }
Example #12
0
        private void Slice(Plane p)
        {
            float epsilon = 0.01f; // TODO: compute proper epsilon value

            List<PolyLine> linePile = new List<PolyLine>(); // Pile of disconnected lines on the slice plane
            List<Vector3> all_points = new List<Vector3>();
            foreach (Face f in this.faces)
            {
                PolyLine newLine = TrianglePlaneIntersect(f, p);

                // Only add lines with exactly 2 points - others are a no match or error
                if (newLine.points.Count() == 2 && (newLine.points[0] - newLine.points[1]).Length> epsilon)
                {
                    linePile.Add(newLine);

                    // Add the vertices to the all_points list - only need to add the first one, the tail will be the head of another point
                    bool matched = false;
                    foreach (Vector3 point in all_points)
                    {
                        if ((point - newLine.points[0]).Length < epsilon)
                        {
                            matched = true;
                            break;
                        }
                    }
                    if (!matched)
                    {
                        all_points.Add(newLine.points[0]);
                    }
                }
            }

            // linePile is a unordered list of line segments.
            // If a line segment is oriented with point[0] on (0, 0, 0) and point[1]
            // somewhere on the positive Y axis, the solid object is in the direction of the positive x axis.
            //
            //              p[1]xxxxxxxxxxxxxxxxxxxxxxxx
            //               xx                       xx
            //               xx  <object over here>   xx
            //               xx                       xx
            //              p[0]xxxxxxxxxxxxxxxxxxxxxxxx
            //

            List<PolyLine> newPolyLines = new List<PolyLine>();
            for (int i = 0; i < linePile.Count(); i++)
            {
                int points = linePile[i].points.Count();

                Vector3 v1 = linePile[i].points[0];
                Vector3 v2 = linePile[i].points[1];

                //DrawCone1(v1, v2);

                List<Vector3> points_on_line = new List<Vector3>();
                foreach (Vector3 v in all_points)
                {
                    if ((v1 - v).Length >= epsilon && (v2 - v).Length >= epsilon && DistanceToCylinder(v1, v2, v) < epsilon)
                    {
                        points_on_line.Add(v);
                    }
                }

                points_on_line.Insert(0, v1);
                points_on_line.Add(v2);

                // Order from v1 to v2
                var sorted = points_on_line.OrderBy(order_vec => (order_vec - v1).Length);

                PolyLine newPolyLine = new PolyLine();
                foreach (Vector3 v in sorted)
                {
                    if (newPolyLine.points.Count() == 0 || (newPolyLine.points[newPolyLine.points.Count() - 1] - v).Length > epsilon)
                    {
                        newPolyLine.points.Add(v);
                    }
                }
                if (newPolyLine.points.Count() >= 2)
                {
                    newPolyLines.Add(newPolyLine);
                }
                if (newPolyLine.points.Count() >= 3)
                {
                    // Shouldn't get here!
                }
            }

            List<LinePointIndices> lpis = new List<LinePointIndices>();
            List<Vector3> vertices = new List<Vector3>();
            List<List<int>> v_lookup = new List<List<int>>();

            foreach (PolyLine l in newPolyLines)
            {
                int lastIndex = -1;
                foreach (Vector3 pointVec in l.points)
                {
                    int currentIndex = -1;
                    for (int i = 0; i < vertices.Count(); i++)
                    {
                        float length = (vertices[i] - pointVec).Length;
                        if (length < epsilon)
                        {
                            currentIndex = i;
                            continue;
                        }
                    }
                    if (currentIndex == -1)
                    {
                        vertices.Add(pointVec);
                        v_lookup.Add(new List<int>());
                        currentIndex = vertices.Count() - 1;
                    }

                    if (lastIndex != -1 && lastIndex != currentIndex)
                    {
                        LinePointIndices line = new LinePointIndices();

                        bool already_matched = false;
                        foreach (int line_index in v_lookup[lastIndex])
                        {
                            LinePointIndices l2 = lpis[line_index];
                            if (l2.indices[1] == currentIndex)
                            {
                                already_matched = true;
                            }
                        }
                        if (!already_matched)
                        {

                            line.indices.Add(lastIndex);
                            line.indices.Add(currentIndex);
                            lpis.Add(line);

                            v_lookup[lastIndex].Add(lpis.Count() - 1);
                            v_lookup[currentIndex].Add(lpis.Count() - 1);
                        }
                    }
                    lastIndex = currentIndex;
                }
            }

            //List<Vector3> scaled = new List<Vector3>();
            List<int> vector_indices_to_see = new List<int>();
            foreach (Vector3 v in vertices)
            {
                //scaled.Add(v / 125);
                vector_indices_to_see.Add(vector_indices_to_see.Count());
            }

            List<LinePointIndices> slices = new List<LinePointIndices>();

            GL.PushMatrix();
            GL.PointSize(10);
            List<int> seenVertices = new List<int>();
            while(vector_indices_to_see.Count() > 0)
            {
                List<int> line_indices = v_lookup [vector_indices_to_see[0]];
                vector_indices_to_see.RemoveAt(0);
                if (line_indices.Count() == 0)
                {
                    continue;
                }
                LinePointIndices line = lpis[line_indices[0]]; // Only need to look at one line with this vertex
                LinePointIndices start_line = new LinePointIndices();
                start_line.indices.Add(line.indices[0]);
                start_line.indices.Add(line.indices[1]);
                GL.Color3(Color.Green);
                DrawCone1(vertices[start_line.indices[0]], vertices[start_line.indices[1]]);
                LinePointIndices loop = FindLoop(seenVertices, p.normal, vertices, v_lookup, lpis, start_line);

                if (loop != null)
                {
                    slices.Add(loop);
                    GL.Color3(Color.LightBlue);
                    GL.Begin(BeginMode.LineLoop);
                    Vector3 add = new Vector3(0, 0, 0);
                    foreach (int i in loop.indices)
                    {
                        vector_indices_to_see.RemoveAll(value => value == i);
                        GL.Vertex3(vertices[i] + add);
                        seenVertices.Add(i);
                        //add += new Vector3(0, 0, 25);
                    }
                    GL.End();
                    //GL.Translate(new Vector3(0, 0, +100));
                }
                //break;
            }
            GL.PointSize(1);
            GL.PopMatrix();

            Vector3 normal = new Vector3(0, 0, 1);
            float toolRadius = 100;
            GL.LineWidth(1);

            List<IntPoint> boundingBox = new List<IntPoint>();
            boundingBox.Add(new IntPoint(-1000, -1000));
            boundingBox.Add(new IntPoint(3000, -1000));
            boundingBox.Add(new IntPoint(3000, 3000));
            boundingBox.Add(new IntPoint(-1000, 3000));

            List<LineLoop> loops = new List<LineLoop>();

            foreach (LinePointIndices l in slices)
            {
                LineStrip line = new LineStrip();
                for (int i = 0; i < l.indices.Count (); i++)
                {
                    line.Append(vertices[l.indices[i]]);
                }
                line.Append(vertices[l.indices[0]]);
                loops.Add(new LineLoop (line));
            }

            if (loops.Count() > 0)
            {
                Vector3 up = new Vector3(0, 0, 1);
                if (Math.Abs (normal.Z) > 0.8)
                {
                    up = new Vector3(1, 0, 0);
                }

                float distance = Vector3.Dot(loops[0].GetVertex(0), normal);

                Matrix4 transform = Matrix4.LookAt(normal * distance, normal * (distance - 1), up);
                Matrix4 inverseTransform = Matrix4.Invert(transform);

                Clipper c = new Clipper();
                c.Clear();

                try
                {
                    // These loops go clockwise
                    foreach (LineLoop loop in loops)
                    {
                        List<IntPoint> polygon = new List<IntPoint>();
                        foreach (Vector3 vertex in loop.Vertices)
                        {
                            Vector3 result = Vector3.Transform(vertex, transform);
                            polygon.Add(new IntPoint((long)result.X, (long)result.Y));
                        }
                        polygon.RemoveAt(0);
                        c.AddPolygon(polygon, PolyType.ptClip);
                        GL.PushMatrix();
                        GL.Translate(new Vector3(0, 0, 100));
                        //loop.Draw();
                        GL.PopMatrix();
                    }
                    List<List<IntPoint>> union = new List<List<IntPoint>>();
                    bool r = c.Execute(ClipType.ctUnion, union, PolyFillType.pftNonZero, PolyFillType.pftNonZero);

                    List<List<IntPoint>> with_offset = Clipper.OffsetPolygons(union, toolRadius, JoinType.jtSquare);
                    List<List<IntPoint>> whatsLeft = Clipper.OffsetPolygons(with_offset, -toolRadius, JoinType.jtRound);

                    List<LineStrip> strips = new List<LineStrip>();
                    foreach (List<IntPoint> polygon in with_offset)
                    {
                        LineStrip strip = new LineStrip();
                        foreach (IntPoint point in polygon)
                        {
                            strip.Append(Vector3.Transform(new Vector3(point.X, point.Y, 0.0f), inverseTransform));
                        }
                        strip.Append(Vector3.Transform(new Vector3(polygon[0].X, polygon[0].Y, 0.0f), inverseTransform));

                        strips.Add(strip);
                        //new LineLoop(strip).Draw();
                    }

                    List<List<IntPoint>> removeArea = new List<List<IntPoint>>();
                    c.Clear();
                    c.AddPolygons(with_offset, PolyType.ptClip);
                    c.AddPolygon(boundingBox, PolyType.ptSubject);
                    List<List<IntPoint>> resultingPolygon = new List<List<IntPoint>>();
                    c.Execute(ClipType.ctDifference, removeArea, PolyFillType.pftNonZero, PolyFillType.pftNonZero);
                    removeArea = Clipper.CleanPolygons(removeArea, toolRadius / 100);

                    c.Clear();
                    c.AddPolygons(removeArea, PolyType.ptClip);
                    PolyTree test = new PolyTree();
                    c.Execute(ClipType.ctUnion, test, PolyFillType.pftNonZero, PolyFillType.pftNonZero);

                    //PolyNode pn = test.GetFirst();
                    //while (pn != null)
                    //{
                    //    if (pn.IsHole)
                    //    {
                    //        LineLoop l = new LineLoop(pn.Contour, inverseTransform);
                    //        l.Draw();
                    //    }
                    //    pn = pn.GetNext();
                    //}
                    List<Polygons> polys = FlattenPolyTree(test);

                    //GL.PushMatrix();
                    foreach (Polygons polygons in polys)
                    {
                        //GL.Translate(new Vector3 (0, 0, 100));
                        //foreach (Polygon polygon in polygons)
                        //{
                        //    LineLoop l = new LineLoop(polygon, inverseTransform);
                        //    l.Draw();
                        //}
                        List<Polygons> paths = ReducePolygon(polygons, toolRadius, inverseTransform);
                        //IOrderedEnumerable<List<IntPoint>> ordered = paths.OrderBy(poly => Clipper.Area(poly));
                        GL.PushMatrix();
                        List<Polygons> paths2 = new List<Polygons>();
                        List<Polygons> paths3 = new List<Polygons>();
                        foreach (Polygons polygons2 in paths)
                        {
                            var newPolys = new Polygons();
                            foreach (Polygon poly in polygons2)
                            {
                                if (Clipper.Area(poly) > 0)
                                {
                                    newPolys.Add(poly);
                                }
                            }
                            paths2.Add(newPolys);

                            //GL.Translate(new Vector3(0, 0, 100));
                            var newInnerPolys = new Polygons();
                            foreach (Polygon poly in polygons2)
                            {

                                if (paths3.Count() == 0)
                                {
                                    //newInnerPoly
                                }
                                if (Clipper.Area(poly) < 0)
                                {
                                  LineLoop l = new LineLoop(poly, inverseTransform);
                                  l.Draw();
                                }
                            }

                        }
                        foreach (Polygons polygons2 in paths2)
                        {
                            GL.Translate(new Vector3(0, 0, 100));
                            foreach (Polygon poly in polygons2)
                            {
                                LineLoop l = new LineLoop(poly, inverseTransform);
                                l.Draw();
                            }
                        }
                        GL.PopMatrix();
                    }
                    //GL.PopMatrix();

                    double boundingBoxArea = Clipper.Area(boundingBox);
                    // Outer Polygon
                    // Inner Polygons
                    //ReducePolygon(boundingBox, with_offset, toolRadius, inverseTransform);

                    //strips = new List<LineStrip>();
                    //double area = 1;
                    //int loopTimes = 0;

                    //List<List<IntPoint>> cutPolygons = new List<List<IntPoint>>();
                    //List<Vector3> parentPoints = new List<Vector3>();
                    //GL.PushMatrix();
                    //while (removeArea.Count() > 0)
                    //{
                    //    List<Vector3> points = new List<Vector3>();
                    //    foreach (List<IntPoint> polygon in removeArea)
                    //    {
                    //        double area = Clipper.Area(polygon);
                    //
                    //        if (area > 0) // Bigger to Smaller
                    //        {
                    //        }
                    //        IntPoint[] newP = new IntPoint[polygon.Count()];
                    //        polygon.CopyTo(newP);
                    //        cutPolygons.Add(new List<IntPoint>(newP));
                    //
                    //
                    //        LineLoop l = new LineLoop(polygon, inverseTransform);
                    //        //l.Draw();
                    //        points.AddRange(l.Vertices);
                    //
                    //        //ReducePolygon(null, polygon, toolRadius, inverseTransform);
                    //        //area += Clipper.Area(polygon);
                    //        //LineStrip strip = new LineStrip();
                    //        //foreach (IntPoint point in polygon)
                    //        //{
                    //        //    strip.Append(Vector3.Transform(new Vector3(point.X, point.Y, 0.0f), inverseTransform));
                    //        //}
                    //        //strip.Append(Vector3.Transform(new Vector3(polygon[0].X, polygon[0].Y, 0.0f), inverseTransform));
                    //
                    //        //strips.Add(strip);
                    //        //new LineLoop(strip).Draw();
                    //    }
                    //
                    //    //GL.Color3(Color.Black);
                    //    //GL.Begin(BeginMode.Lines);
                    //    //foreach (Vector3 v in points)
                    //    //{
                    //    //    foreach (Vector3 v2 in parentPoints)
                    //    //    {
                    //    //        if ((v - v2).Length < toolRadius * 2)
                    //    //        {
                    //    //            GL.Vertex3(v);
                    //    //            GL.Vertex3(v2);
                    //    //        }
                    //    //    }
                    //    //}
                    //    //GL.End();
                    //
                    //    parentPoints = points;
                    //    removeArea = Clipper.OffsetPolygons(removeArea, -toolRadius, JoinType.jtRound);
                    //    removeArea = Clipper.CleanPolygons(removeArea, toolRadius / 100);
                    //}
                    //GL.PopMatrix();

                    //IOrderedEnumerable<List<IntPoint>> ordered = cutPolygons.OrderBy(poly => Clipper.Area(poly));
                    //
                    //GL.PushMatrix();
                    //foreach (List<IntPoint> poly in ordered)
                    //{
                    //    GL.Translate(new Vector3(0, 0, 100));
                    //    LineLoop l = new LineLoop(poly, inverseTransform);
                    //    l.Draw();
                    //}
                    //GL.PopMatrix();

                    ////strips = new List<LineStrip>();
                    //GL.Color3(Color.Red);
                    //GL.LineWidth(2);
                    //foreach (List<IntPoint> polygon in whatsLeft)
                    //{
                    //    LineStrip strip = new LineStrip();
                    //    foreach (IntPoint point in polygon)
                    //    {
                    //        strip.Append(Vector3.Transform(new Vector3(point.X, point.Y, 0.0f), inverseTransform));
                    //    }
                    //    strip.Append(Vector3.Transform(new Vector3(polygon[0].X, polygon[0].Y, 0.0f), inverseTransform));
                    //
                    //    strips.Add(strip);
                    //    new LineLoop(strip).Draw();
                    //}
                    //GL.LineWidth(1);

                }
                catch (Exception e)
                {
                }
            }
        }
Example #13
0
        public static WeaklySimplePolygon Union(WeaklySimplePolygon lhs, WeaklySimplePolygon rhs)
        {
            WeaklySimplePolygon res = new WeaklySimplePolygon();

            IntersectionResolution ir = GetIntersectionInfo(lhs, rhs);

            //preprocessing
            for (int i = -1; i < lhs.holes.Count; i++)
            {
                if (i == -1 && (!ir.lhs.ContainsKey(-1)) && !lhs.verts[0].IsInside(rhs))
                {
                }
                //if(ir.lhs.ContainsKey()
            }


            List <IntersectionPair> currentLoop = new List <IntersectionPair>();

            //this loop finds the next IntersectionPair in the loop
            //and when a loop is complete, outputs it into res
            while (ir.intersections.Count != 0)
            {
                //start off a random pair if we need to
                if (currentLoop.Count == 0)
                {
                    currentLoop.Add(ir.intersections[0]);
                }

                //find the next intersection and store it in nearestIntersection
                IntersectionPair nearestIntersection = null;
                IntersectionPair lastIntersection    = currentLoop.Last();
                TraversalMode    mode = (lastIntersection.lhs.mode == TraversalMode.exiting) ? TraversalMode.lhs : TraversalMode.rhs;
                //Dictionary<int, int> nextQueue =

                foreach (IntersectionPair info in ir.intersections)
                {
                    if (info.lhs.index == lastIntersection.lhs.index && info.rhs.index == lastIntersection.rhs.index && info != lastIntersection)
                    {
                        if (mode == TraversalMode.lhs)
                        {
                            //traversing lhs
                            if (nearestIntersection == null)
                            {
                                nearestIntersection = info;
                            }
                            else
                            {
                                if (nearestIntersection.lhs.dist < lastIntersection.lhs.dist)
                                {
                                    if (info.lhs.dist > lastIntersection.lhs.dist || info.lhs.dist < nearestIntersection.lhs.dist)
                                    {
                                        nearestIntersection = info;
                                    }
                                }
                                else
                                {
                                    if (info.lhs.dist < nearestIntersection.lhs.dist && info.lhs.dist > lastIntersection.lhs.dist)
                                    {
                                        nearestIntersection = info;
                                    }
                                }
                            }
                        }
                        else
                        {
                            //traversing rhs
                            if (nearestIntersection == null)
                            {
                                nearestIntersection = info;
                            }
                            else
                            {
                                if (nearestIntersection.rhs.dist < lastIntersection.rhs.dist)
                                {
                                    if (info.rhs.dist > lastIntersection.rhs.dist || info.rhs.dist < nearestIntersection.rhs.dist)
                                    {
                                        nearestIntersection = info;
                                    }
                                }
                                else
                                {
                                    if (info.rhs.dist < nearestIntersection.rhs.dist && info.rhs.dist > lastIntersection.rhs.dist)
                                    {
                                        nearestIntersection = info;
                                    }
                                }
                            }
                        }
                    }
                }

                //do what we must with this intersection, we might be done with the loop
                if (nearestIntersection == currentLoop.First())
                {
                    //loop is done, create the loop with actual segments and such
                    LineLoop loop = new LineLoop();

                    //segment mode
                    TraversalMode segMode = (currentLoop.First().lhs.mode == TraversalMode.exiting) ? TraversalMode.lhs : TraversalMode.rhs;
                    for (int i = 0; i < currentLoop.Count; i++)
                    {
                        IntersectionPair info     = currentLoop[i];
                        IntersectionPair nextInfo = currentLoop[(i + 1) % currentLoop.Count];

                        loop.Add(info.vert);

                        //select the correct polygon and loop
                        WeaklySimplePolygon opPoly    = (segMode == TraversalMode.lhs) ? lhs : rhs;
                        int      loopIndex            = (segMode == TraversalMode.lhs) ? info.lhs.index : info.rhs.index;
                        LineLoop opLoop               = (loopIndex == -1) ? opPoly.verts : opPoly.holes[loopIndex];
                        int      startSegment         = ((segMode == TraversalMode.lhs) ? (info.lhs.segment + 1) : info.rhs.segment + 1) % opLoop.Count;
                        int      endSegment           = (segMode == TraversalMode.lhs) ? nextInfo.lhs.segment : nextInfo.rhs.segment;
                        int      endSegmentPlusOneMod = (endSegment + 1) % opLoop.Count;

                        bool first = (segMode == TraversalMode.lhs) ? (info.lhs.dist > nextInfo.lhs.dist) : (info.rhs.dist > nextInfo.rhs.dist);
                        for (int currentSegment = startSegment;
                             (currentSegment != endSegmentPlusOneMod) || first;
                             currentSegment = (currentSegment + 1) % opLoop.Count)
                        {
                            loop.Add(opLoop[currentSegment]);
                            if (first)
                            {
                                first = false;
                            }
                        }

                        if (segMode == TraversalMode.lhs)
                        {
                            segMode = TraversalMode.rhs;
                        }
                        else
                        {
                            segMode = TraversalMode.lhs;
                        }
                    }

                    res.holes.Add(loop);

                    foreach (IntersectionPair info in currentLoop)
                    {
                        ir.intersections.Remove(info);
                    }
                    currentLoop.Clear();
                }
                else
                {
                    currentLoop.Add(nearestIntersection);
                }
            }

            return(res);
        }
Example #14
0
 public WeaklySimplePolygon()
 {
     verts = new LineLoop();
     holes = new List <LineLoop>();
 }
Example #15
0
            /// <summary>
            /// Trim interior loops from the line
            /// </summary>
            public void Clean(Vector3 normal)
            {
                List<int> remove = new List<int>();
                for (int i = 0; i < indices.Count(); i++)
                {
                    Vector3 v1 = GetVertex(i);
                    Vector3 v2 = GetVertex((i + 1) % indices.Count());
                    for (int j = 2; j < indices.Count() - 1; j++)
                    {
                        int j1 = (j + i) % indices.Count();
                        int j2 = (j + i + 1) % indices.Count();
                        Vector3 v3 = GetVertex(j1);
                        Vector3 v4 = GetVertex(j2);

                        Vector3 n1 = v2 - v1;
                        Vector3 n2 = v4 - v3;
                        n1.Normalize();
                        n2.Normalize();

                        if ((n1 - n2).Length < 0.0001f)
                        {
                            // No crossing, same direction
                            continue;
                        }

                        Vector3 perp = Vector3.Cross(normal, n2);
                        Plane p = new Plane ();

                        //GL.Begin(BeginMode.Lines);
                        //GL.Vertex3(v4);
                        //GL.Vertex3(v4 + perp * 100);
                        //GL.End();
                        p.normal = perp;
                        p.point = v3;

                        float distance = p.Distance(v1, n1);
                        if (distance > 0 && distance < (v2 - v1).Length && (Vector3.Dot(perp, n1) < 0))//!float.IsInfinity(distance))
                        {
                            Vector3 point = n1 * distance + v1;
                            if (DistanceToCylinder (v3, v4, point) < 0.01f)
                            {
                                for (int k = 0; k < j; k++)
                                {
                                    int removeIndex = (i + 1) % indices.Count();
                                    indices.RemoveAt(removeIndex);
                                }
                                vertices.Add(point);
                                indices.Insert(i + 1, vertices.Count() - 1);
                                //GL.PointSize(15);
                                //GL.Color3(Color.Turquoise);
                                //GL.Begin(BeginMode.Points);
                                //GL.Vertex3(point);
                                //
                                //GL.End();
                                //GL.PointSize(1);
                                i = i - 1;
                                continue;
                            }
                        }
                    }
                }
                LineLoop n = new LineLoop(this);
                this.indices = n.indices;
                this.vertices = n.vertices;
            }
Example #16
0
 public PolygonNode(LineLoop loop, PolygonNode parent)
 {
     this.loop     = loop;
     this.parent   = parent;
     this.children = new List <PolygonNode>();
 }
Example #17
0
        public LineLoop Simplify()
        {
            List <LineLoop> remainingLoops = holes.ToList();

            remainingLoops.Insert(0, verts.Clone());

            //iterate over each hole, trying to find a line that cuts the hole out without intersecting anything else
            while (remainingLoops.Count > 1)
            {
                LineLoop hole = remainingLoops[1];

                bool holeDone              = false;
                int  foundVertexIndex      = -1;
                int  foundLoopIndex        = -1;
                int  foundOtherVertexIndex = -1;

                //we have go into each loop including the main loop at index 0
                for (int loopIndex = 0; loopIndex < remainingLoops.Count; loopIndex++)
                {
                    if (loopIndex == 1)
                    {
                        continue;                 //
                    }
                    LineLoop loop = remainingLoops[loopIndex];

                    //check each vertex in this hole...
                    for (int p0Index = 0; p0Index < hole.Count; p0Index++)
                    {
                        gvec2 p0 = hole[p0Index];


                        //and make a segment with each vertex in this loop...
                        for (int p1Index = 0; p1Index < loop.Count; p1Index++)
                        {
                            gvec2 p1 = loop[p1Index];

                            //we have now obtained our line segment that must be checked for collision against every pre-existing line segment
                            //this operation is important enough to have its own function
                            if (!AnyIntersections(remainingLoops.ToArray(), 1, p0Index, loopIndex, p1Index))
                            {
                                //we're almost done, just make sure it isn't the wrong side of a hole cutting edge
                                bool valid = true;

                                {
                                    gvec2 n0   = (p0 - p1);
                                    gvec2 p0n0 = (loop[(p1Index - 1 + loop.Count) % loop.Count] - p1);
                                    gvec2 p0n1 = (loop[(p1Index + 1) % loop.Count] - p1);

                                    double ap0n0 = Math.Atan2(p0n0.y, p0n0.x) + Math.PI * 2;
                                    double an0   = Math.Atan2(n0.y, n0.x) + Math.PI * 2; if (an0 < ap0n0)
                                    {
                                        an0 += Math.PI * 2;
                                    }
                                    double ap0n1 = Math.Atan2(p0n1.y, p0n1.x) + Math.PI * 2; if (ap0n1 < ap0n0)
                                    {
                                        ap0n1 += Math.PI * 2;
                                    }

                                    if (an0 > ap0n0 && an0 < ap0n1)
                                    {
                                        valid = false;
                                    }
                                }

                                if (valid)
                                {
                                    gvec2 n0   = (p1 - p0);
                                    gvec2 p0n0 = (hole[(p1Index - 1 + hole.Count) % hole.Count] - p0);
                                    gvec2 p0n1 = (hole[(p1Index + 1) % hole.Count] - p0);

                                    double ap0n0 = Math.Atan2(p0n0.y, p0n0.x) + Math.PI * 2;
                                    double an0   = Math.Atan2(n0.y, n0.x) + Math.PI * 2; if (an0 < ap0n0)
                                    {
                                        an0 += Math.PI * 2;
                                    }
                                    double ap0n1 = Math.Atan2(p0n1.y, p0n1.x) + Math.PI * 2; if (ap0n1 < ap0n0)
                                    {
                                        ap0n1 += Math.PI * 2;
                                    }

                                    if (an0 > ap0n0 && an0 < ap0n1)
                                    {
                                        valid = false;
                                    }
                                }


                                if (valid)
                                {
                                    holeDone              = true;
                                    foundVertexIndex      = p0Index;
                                    foundLoopIndex        = loopIndex;
                                    foundOtherVertexIndex = p1Index;
                                    break;
                                }
                            }
                        }

                        if (holeDone)
                        {
                            break;
                        }
                    }

                    if (holeDone)
                    {
                        break;
                    }
                }

                if (!holeDone)
                {
                    throw new Exception("Found no way out for a hole");
                }

                Console.WriteLine("holeDone: " + holeDone);
                Console.WriteLine("foundVertexIndex: " + foundVertexIndex);
                Console.WriteLine("foundHoleIndex: " + (foundLoopIndex == -1 ? "main" : foundVertexIndex.ToString()));
                Console.WriteLine("foundHoleVertexIndex: " + foundOtherVertexIndex);

                //we need this conditional to account for the main loop winding ccw and holes winding cw
                if (foundLoopIndex == 0)
                {
                    remainingLoops[0] = LineLoop.PseudoSimpleJoin(remainingLoops[0], foundOtherVertexIndex, hole, foundVertexIndex, false, false);
                    remainingLoops.RemoveAt(1);
                }
                else
                {
                    remainingLoops[1] = LineLoop.PseudoSimpleJoin(remainingLoops[foundLoopIndex], foundOtherVertexIndex, hole, foundVertexIndex, false, false);
                    remainingLoops.RemoveAt(foundLoopIndex);
                }
            }

            return(remainingLoops[0]);
        }