示例#1
0
        private void boundaryCheckButton_Click(object sender, EventArgs e)
        {
            float xMin = -router.ToolDiameter;
            float xMax = router.ToolDiameter;
            float yMin = -router.ToolDiameter;
            float yMax = router.ToolDiameter;

            foreach (Object o in drawing3D.GetObjects())
            {
                if (o is TriangleMeshGUI)
                {
                    var triangles = o as TriangleMeshGUI;
                    xMin = Math.Min(triangles.MinPoint.X - router.ToolDiameter + triangles.Offset.X, xMin);
                    xMax = Math.Max(triangles.MaxPoint.X + router.ToolDiameter + triangles.Offset.X, xMax);
                    yMin = Math.Min(triangles.MinPoint.Y - router.ToolDiameter + triangles.Offset.Y, yMin);
                    yMax = Math.Max(triangles.MaxPoint.Y + router.ToolDiameter + triangles.Offset.Y, yMax);
                }
            }

            LineStrip r = new LineStrip();

            r.Append(new Vector3(xMin, yMin, router.MoveHeight));
            r.Append(new Vector3(xMax, yMin, router.MoveHeight));
            r.Append(new Vector3(xMax, yMax, router.MoveHeight));
            r.Append(new Vector3(xMin, yMax, router.MoveHeight));
            r.Append(new Vector3(xMin, yMin, router.MoveHeight));
            router.RoutPath(r, false, Vector3.Zero);
            router.Complete();
        }
示例#2
0
        public void RoutPath(LineStrip line, bool backwards, Vector3 offset)
        {
            bool first = true;

            foreach (Vector3 point in line.Vertices)
            {
                // TODO: Pick some unit and stick with it!  Inches would be fine.
                Vector3 pointOffset = point + offset;

                MoveTool m = new MoveTool(pointOffset, MoveTool.SpeedType.Cutting);
                if (first)
                {
                    first = false;

                    if ((finalPosition.Xy - pointOffset.Xy).Length > .0001)
                    {
                        // Need to move the router up, over to new position, then down again.
                        MoveTool m1 = new MoveTool(new Vector3(finalPosition.X, finalPosition.Y, move_height), MoveTool.SpeedType.Rapid);
                        MoveTool m2 = new MoveTool(new Vector3(m.Target.X, m.Target.Y, move_height), MoveTool.SpeedType.Rapid);
                        AddCommand(m1);
                        AddCommand(m2);
                    }
                }
                AddCommand(m);
            }
        }
示例#3
0
            /// <summary>
            /// Generate a set of tool paths which will completely remove the material specified in
            /// the polygons, plus an offset equal to the radius of the tool used.
            /// </summary>
            /// <param name="polygons"></param>
            /// <param name="maxShrink">maximum distance between disjoint paths</param>
            /// <returns></returns>
            public static List <LineStrip> ObliterateSlice(Slice polygons, float maxShrink, bool reverse = false)
            {
                List <LineStrip> lines = new List <LineStrip>();

                foreach (Slice slice in polygons.IndividualPolygons())
                {
                    PathTree tree   = new PathTree(reverse);
                    Slice    inside = new Slice(slice.GetLines(Slice.LineType.Hole), slice.Plane);
                    Slice    shrink = new Slice(slice);
                    while (shrink.Area() > 0)
                    {
                        shrink = new Slice(shrink.GetLines(Slice.LineType.Outside), shrink.Plane);
                        foreach (var a in shrink.IndividualPolygons())
                        {
                            if (!tree.AddPolygon(a))
                            {
                                // The new polygon didn't fit into the path tree...  shouldn't get here.
                            }
                        }

                        shrink.Offset(-maxShrink);
                        shrink.Subtract(inside);
                    }

                    LineStrip toolPath = new LineStrip();
                    tree.GenerateToolPath(toolPath, tree.CreatePath(), maxShrink * 2.0f);
                    lines.Add(toolPath);
                }
                return(lines);
            }
示例#4
0
        public Tabs(LineStrip boundary, float toolRadius, bool inside = false)
        {
            originalBoundary = new Slice(new LineStrip[] { boundary }, new Plane(Vector3.UnitZ, Vector3.Zero));
            float offset = toolRadius;

            if (inside)
            {
                offset = -offset;
            }
            Slice slice = new Slice(originalBoundary);

            slice.Offset(offset);
            this.boundary   = slice.GetLines(Slice.LineType.Outside).First(s => true);
            this.toolRadius = toolRadius;

            float length  = this.boundary.Length(LineStrip.Type.Closed);
            int   numTabs = (int)(length / desiredSpacing);

            if (numTabs < minTabs)
            {
                numTabs = 0;
            }


            float tabSpacing = length / numTabs;

            tabLocations = new List <Vector3>();
            foreach (var point in this.boundary.PointsAlongLine(tabSpacing, tabSpacing / 2.0f))
            {
                tabLocations.Add(point);
            }
        }
示例#5
0
        /// <summary>
        /// Create another line strip which follows the same path, but avoids tab locations.
        /// NOTE: this currently only works on closed input lines.  The algorithm could
        /// be modified to work correctly with open paths too, but that's not needed yet.
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public LineStrip AvoidTabs(LineStrip input)
        {
            LineStrip ret = new LineStrip();

            foreach (var segment in input.Segments(LineStrip.Type.Closed))
            {
                if (segment.Length < 0.0001f)
                {
                    continue;
                }
                if (segment.A.Z > tabHeight && segment.B.Z > tabHeight)
                {
                    ret.Append(segment.B);
                    continue;
                }
                List <LineSegment> remainingSegments = new List <LineSegment>();
                remainingSegments.Add(segment);
                foreach (Vector3 tab in this.TabLocations)
                {
                    var i = new LineSegmentCircleIntersect(segment, tab, tabRadius + toolRadius);
                    if (i.type == LineSegmentCircleIntersect.IntersectType.Segment)
                    {
                        List <LineSegment> temp = new List <LineSegment>();

                        foreach (var seg in remainingSegments)
                        {
                            temp.AddRange(seg.Subtract(i.IntersectSegment));
                        }
                        remainingSegments = temp;
                    }
                }
                remainingSegments.RemoveAll(s => s.Length < 0.0001f);

                if (remainingSegments.Count == 0)
                {
                    // Entire segment is within a tab
                    TestAddPoint(ClearHeight(segment.B, tabHeight), ret.Vertices);
                }
                else
                {
                    // Everything described in "remainingSegments" is outside of the tab, and the spaces
                    // between are on the tab.  The path between is known since it's always a straight line.
                    remainingSegments.Sort((s1, s2) => (s1.A - segment.A).Length.CompareTo((s2.A - segment.A).Length));
                    foreach (var s in remainingSegments)
                    {
                        TestAddPoint(ClearHeight(s.A, tabHeight), ret.Vertices);
                        TestAddPoint(s.A, ret.Vertices);
                        TestAddPoint(s.B, ret.Vertices);
                        TestAddPoint(ClearHeight(s.B, tabHeight), ret.Vertices);
                    }
                    TestAddPoint(ClearHeight(segment.B, tabHeight), ret.Vertices);
                }
            }

            return(ret);
        }
示例#6
0
            private void AddRoutPoint(Slice currentPolygon, Vector3 newPoint, bool check = true)
            {
                if (routs.Count == 0)
                {
                    routs.Add(new LineStrip());
                }
                LineStrip currentRout = routs[routs.Count - 1];

                if (check)
                {
                    if (currentRout.Vertices.Count > 0)
                    {
                        Slice larger = new Slice(currentPolygon);
                        larger.Offset(toolRadius * 1.05f);
                        Vector3   lastPoint = currentRout.Vertices[currentRout.Vertices.Count - 1];
                        LineStrip path      = new LineStrip();
                        path.Append(lastPoint);
                        path.Append(newPoint);
                        Slice test = new Slice(path, toolRadius * 2.0f, currentPolygon.Plane);


                        if (!larger.Contains(test))
                        {
                            // Can't move at this level - need to go to the save Z move height.
                            currentRout = new LineStrip();
                            routs.Add(currentRout);
                            //DrawSlice(Color.Black, Color.Red, test);
                        }
                        else
                        {
                            //DrawSlice(Color.Black, Color.Green, test);
                        }
                        //larger.Subtract(test);
                        //GL.Translate(0, 0, 100);
                    }
                }
                // If the Z height changed, move to the new position and and drop, or rise and then move.
                if (currentRout.Vertices.Count > 0)
                {
                    var lastPoint = currentRout.Vertices[currentRout.Vertices.Count - 1];
                    if (newPoint.Z < lastPoint.Z)
                    {
                        currentRout.Vertices.Add(new Vector3(newPoint.X, newPoint.Y, lastPoint.Z));
                    }
                    else if (newPoint.Z > lastPoint.Z)
                    {
                        currentRout.Vertices.Add(new Vector3(lastPoint.X, lastPoint.Y, newPoint.Z));
                    }
                }
                currentRout.Vertices.Add(newPoint);
            }
示例#7
0
 public override void AccumulateStrips(LineStrip vertices)
 {
     if (triangleCount <= 0 || Points.Count() < 2)
     {
         return;
     }
     vertices.NumTriangles += triangleCount;
     if (vertices.Vertices.Count > 0)
     {
         vertices.Vertices.Add(vertices.Vertices.Last());
         vertices.Vertices.Add(triangles[0]);
         vertices.NumTriangles += 1;
     }
     vertices.Vertices.AddRange(triangles);
 }
示例#8
0
 public override void AccumulateStrips(LineStrip vertices)
 {
     if (triangleCount <= 0 || Points.Count() < 2)
     {
         return;
     }
     vertices.NumTriangles += triangleCount;
     if (vertices.Vertices.Count > 0)
     {
         vertices.Vertices.Add(vertices.Vertices.Last());
         vertices.Vertices.Add(triangles[0]);
         vertices.NumTriangles += 1;
     }
     vertices.Vertices.AddRange(triangles);
 }
示例#9
0
        public override void AccumulateStrips(LineStrip strips)
        {
            for (int i = 0; i < _stripVertices.Count; i++)
            {
                strips.NumTriangles += _stripTriangleCounts[i];

                if (strips.Vertices.Count > 0)
                {
                    strips.Vertices.Add(strips.Vertices.Last());
                    strips.Vertices.Add(_stripVertices[i][0]);
                    strips.Vertices.Add(_stripVertices[i][0]);
                    strips.NumTriangles += 1;
                }
                strips.Vertices.AddRange(_stripVertices[i]);
            }
        }
示例#10
0
        public static List <LineStrip> PlanPaths(TriangleMesh triangles, List <Tabs> tabs, Router router)
        {
            List <LineStrip> routs = new List <LineStrip>();

            foreach (Tabs tab in tabs)
            {
                tab.TabHeight = router.TabHeight;
            }

            float toolRadius      = router.ToolDiameter / 2.0f;
            float maxCutDepth     = router.MaxCutDepth;
            float lastPassHeight  = router.LastPassHeight;
            float cleanPassFactor = 0.90f; // 90% of the tool radius will be removed on the clean pass

            float minZ = triangles.MinPoint.Z;
            float maxZ = triangles.MaxPoint.Z;

            var slices = GetSlices(triangles, router);
            //GL.PushMatrix();
            //foreach (var s in slices)
            //{
            //    GL.Translate(triangles.MaxPoint.X - triangles.MinPoint.X, 0, 0);
            //    DrawSlice(Color.Orange, Color.Black, s);
            //}
            //GL.PopMatrix();

            Slice top = slices[0];

            slices.RemoveAt(0);
            Slice boundary = new Slice(slices[slices.Count - 1]);

            boundary.Offset(toolRadius * (cleanPassFactor + 1.05f)); // Note: this is slightly larger to allow some polygon width to exist

            // Enable complete removal of holes with no tabs
            foreach (var tab in tabs)
            {
                if (tab.TabLocations.Count() == 0)
                {
                    boundary.Union(tab.Boundary);
                }
            }

            top.SubtractFrom(boundary);

            //GL.PushMatrix();
            //GL.Translate(0, 0, 1);
            //DrawSlice(Color.Black, Color.DarkGray, boundary);
            //GL.PopMatrix();

            Slice holes = top.PolygonsWithoutHoles();

            List <Hole> holeRouts = new List <Hole>();

            foreach (var polygon in holes.IndividualPolygons())
            {
                holeRouts.Add(new Hole(polygon, toolRadius, cleanPassFactor));
            }

            foreach (Slice current in slices)
            {
                current.Offset(toolRadius);
                //GL.PushMatrix();
                //GL.Translate(0, 0, -0.001f);
                ////DrawSlice(Color.Tan, Color.Gray, boundary);
                //GL.PopMatrix();
                ////DrawSlice(Color.Red, Color.Blue, current);

                Slice original = new Slice(current);
                current.SubtractFrom(boundary);

                // current will now be several polygons representing the area to rout out, minus the tool radius offset on either side.
                // Split it into polygons around the outside and inside of parts (the first two will be outside polygons, the next two inside, next two outside, ...).
                Slice outsidePairs = current.GetOutsidePairs();
                //DrawSlice(Color.Gold, Color.Yellow, outsidePairs);

                Slice insidePairs = current.GetInsidePairs();
                //DrawSlice(Color.Orange, Color.NavajoWhite, insidePairs);


                // If a polygon has no holes, that means it's a hole in the actual shape to be cut out.
                // These can be cut first before outside cuts are done.
                holes = current.PolygonsWithoutHoles();
                foreach (var holePolygon in insidePairs.PolygonsWithoutHoles().IndividualPolygons())
                {
                    foreach (var hole in holeRouts)
                    {
                        if (hole.Contains(holePolygon))
                        {
                            hole.AddPolygon(holePolygon);
                            break;
                        }
                    }
                }


                // Rout all outside paths.  These will be done from top down, one layer at a time for structural reasons.
                // For the top several layers, two paths could be combined...
                var outsideRouts = RoutAreasWithHoles(insidePairs.PolygonsWithHoles(), toolRadius, cleanPassFactor, tabs, true);
                var newLines     = new List <LineStrip>();
                foreach (var line in outsideRouts)
                {
                    var r = new LineStrip();
                    r.AddRange(line.Vertices);
                    r.Append(line.Vertices[0]);
                    r.Vertices.Reverse();
                    newLines.Add(r);
                }
                routs.AddRange(newLines);


                outsideRouts = RoutAreasWithHoles(outsidePairs, toolRadius, cleanPassFactor, tabs, false);
                newLines     = new List <LineStrip>();
                foreach (var line in outsideRouts)
                {
                    var r = new LineStrip();
                    r.AddRange(line.Vertices);
                    r.Append(line.Vertices[0]);
                    newLines.Add(r);
                }
                routs.AddRange(newLines);
            }

            foreach (var hole in holeRouts)
            {
                var newRouts = new List <LineStrip>();
                foreach (var line in hole.GetRouts())
                {
                    LineStrip r = new LineStrip();
                    // Note: these might not start and end in the same place, but that's OK.
                    r.AddRange(line.Vertices);
                    newRouts.Add(r);
                }
                routs.InsertRange(0, newRouts);
            }

            // Adjust the lowest point - allow plunging through the bottom of the material for a clean cut.
            foreach (LineStrip r in routs)
            {
                for (int i = 0; i < r.Vertices.Count; i++)
                {
                    var point = r.Vertices[i];
                    if (point.Z < (minZ + .005f))
                    {
                        r.Vertices[i] = new Vector3(point.X, point.Y, lastPassHeight);
                    }
                }
            }
            return(routs);
        }
示例#11
0
            /// <summary>
            /// Generate a tool path from the current path tree
            /// </summary>
            /// <param name="start">line strip to add path information</param>
            /// <param name="thisPath">line strip representing the path at the current level</param>
            /// <param name="maxDistance">maximum distance to jump from a parent path to a child path</param>
            private void GenerateToolPath(LineStrip start, LineStrip thisPath, float maxDistance)
            {
                List <PathTree> childs = new List <PathTree>();

                foreach (PathTree child in children)
                {
                    childs.Add(child);
                }

                var pathVertices = thisPath.Vertices.Count;

                for (int i = 0; i < pathVertices; i++)
                {
                    var p1 = thisPath.Vertices[i];
                    var p2 = thisPath.Vertices[(i + 1) % pathVertices];

                    Segment parentSegment = new Segment(p1, p2);
                    start.Append(p1);

                    int childIndex   = 0;
                    int closestIndex = 0;

                    for (int childTreeIndex = 0; childTreeIndex < childs.Count; childTreeIndex++)
                    {
                        var  child         = childs[childTreeIndex];
                        bool found         = false;
                        var  childPath     = child.CreatePath();
                        var  childVertices = childPath.Vertices.Count;

                        // Prefer point to point matches
                        var closest = maxDistance;
                        for (childIndex = 0; childIndex < childVertices; childIndex++)
                        {
                            var c1  = childPath.Vertices[childIndex];
                            var len = (c1 - p1).Length;
                            if (len < closest)
                            {
                                closest      = len;
                                closestIndex = childIndex;
                                found        = true;
                            }
                        }

                        // If a point to point match isn't found, look for line to point matches.
                        if (!found)
                        {
                            closest = maxDistance;
                            Vector3 insertPoint  = Vector3.Zero;
                            bool    insertParent = false;

                            // If there is no point to point match, find a point to line match.
                            for (childIndex = 0; childIndex < childVertices; childIndex++)
                            {
                                var     c1           = childPath.Vertices[childIndex];
                                var     c2           = childPath.Vertices[(childIndex + 1) % childVertices];
                                Segment childSegment = new Segment(c1, c2);

                                var fromParentSegment = parentSegment.DistanceTo(c1);
                                if (fromParentSegment < closest)
                                {
                                    insertParent = true;
                                    closest      = fromParentSegment;
                                    insertPoint  = parentSegment.PointOnLine;
                                    closestIndex = childIndex;
                                    found        = true;
                                }

                                var fromChildSegment = childSegment.DistanceTo(p1);
                                if (fromChildSegment < closest)
                                {
                                    // Note: this happens very rarely
                                    insertParent = false;
                                    closest      = fromChildSegment;
                                    insertPoint  = childSegment.PointOnLine;
                                    closestIndex = childIndex;
                                    found        = true;
                                }
                            }
                            if (found)
                            {
                                if (insertParent)
                                {
                                    p1 = insertPoint;
                                    start.Append(p1);
                                }
                                else
                                {
                                    closestIndex++;
                                    childPath.Vertices.Insert(closestIndex, insertPoint);
                                }
                            }
                        }

                        if (found)
                        {
                            // Reorder the child vertices
                            var last = childPath.Vertices.GetRange(0, closestIndex);
                            childPath.Vertices.RemoveRange(0, closestIndex);
                            childPath.Vertices.AddRange(last);

                            child.GenerateToolPath(start, childPath, maxDistance);
                            start.Append(p1);

                            childs.RemoveAt(childTreeIndex);
                            childTreeIndex--;
                        }
                    }
                }

                if (childs.Count > 0)
                {
                    // No path to these children - need to handle them some other way
                    badTrees.AddRange(childs);
                }

                // Complete the loop
                start.Append(thisPath.Vertices[0]);
            }
示例#12
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;
                //}
            }
示例#13
0
 public abstract void AccumulateStrips(LineStrip vertices);
示例#14
0
 public TabsGUI(LineStrip boundary, float toolRadius, bool inside = false) : base(boundary, toolRadius, inside)
 {
     drawSlice = new Slice(this.TabPath, toolRadius * 2.0f, new Plane(Vector3.UnitZ, Vector3.Zero), true);
 }
示例#15
0
            private void LineLoopFromLineStrip(LineStrip l)
            {
                foreach (Vector3 v in l.Vertices)
                {
                    this.Append(v);
                }
                if (indices.Count() < 3)
                {
                    throw new Exception("Cannot make a loop from a line with fewer than 3 vertices");
                }
                if (indices[0] != indices[indices.Count() - 1])
                {
                    throw new Exception("Line is not a loop - the first and last vertex must be the same");
                }

                // Remove the last index - it's redundant.
                indices.RemoveAt(indices.Count() - 1);

                // Test if the connection back to the first vertex makes the last vertex unnecessary
                Vector3 v1 = vertices[indices[indices.Count() - 1]];
                Vector3 v2 = vertices[indices[0]];
                Vector3 v3 = vertices[indices[1]];
                if (OnSameLine(v1, v2, v3))
                {
                    indices.RemoveAt(0);
                }
            }
示例#16
0
 public LineLoop(LineStrip l)
 {
     LineLoopFromLineStrip(l);
 }
示例#17
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)
                {
                }
            }
        }
示例#18
0
 public override void AccumulateStrips(LineStrip vertices)
 {
 }
示例#19
0
 public abstract void AccumulateStrips(LineStrip vertices);
示例#20
0
 public LineLoop(List<IntPoint> polygon, Matrix4 transform)
 {
     LineStrip l = new LineStrip();
     foreach (IntPoint point in polygon)
     {
         l.Append(Vector3.Transform(new Vector3(point.X, point.Y, 0.0f), transform));
     }
     l.Append(Vector3.Transform(new Vector3(polygon[0].X, polygon[0].Y, 0.0f), transform));
     LineLoopFromLineStrip(l);
 }