public List<Polygon> Clip(Polygon p1, Polygon p2, OpType operation)
        {
            List<IntPoint> pol1 = new List<IntPoint>();
            List<IntPoint> pol2 = new List<IntPoint>();
            List<List<IntPoint>> res = new List<List<IntPoint>>();

            foreach (Point point in p1.Points) {
                pol1.Add(new IntPoint(point.X, point.Y));
            }
            foreach (Point point in p2.Points) {
                pol2.Add(new IntPoint(point.X, point.Y));
            }

            Clipper clipper = new Clipper();
            clipper.AddPolygon(pol1, PolyType.ptSubject);
            clipper.AddPolygon(pol2, PolyType.ptClip);

            switch (operation) {
                case OpType.Difference:
                    clipper.Execute(ClipType.ctDifference, res);
                    break;
                case OpType.Intersection:
                    clipper.Execute(ClipType.ctIntersection, res);
                    break;
                case OpType.Union:
                    clipper.Execute(ClipType.ctUnion, res);
                    break;
                case OpType.Xor:
                    clipper.Execute(ClipType.ctXor, res);
                    break;
            }
            List<Polygon> ret = new List<Polygon>();

            foreach (var poly in res) {
                Polygon pol = new Polygon() { Points = new List<Point>() };

                foreach (var poi in poly) {
                    pol.Points.Add(new Point() { X = poi.X, Y = poi.Y });
                }

                ret.Add(pol);
            }
            return ret;
        }
            public PolyOffsetBuilder(Polygons pts, Polygons solution, double delta, JoinType jointype, double MiterLimit = 2)
            {
                //precondtion: solution != pts

                if (delta == 0)
                {
                    solution = pts;
                    return;
                }

                this.pts = pts;
                this.delta = delta;
                if (MiterLimit <= 1) MiterLimit = 1;
                double RMin = 2/(MiterLimit*MiterLimit);

                normals = new List<DoublePoint>();

                double deltaSq = delta*delta;
                solution.Clear();
                solution.Capacity = pts.Count;
                for (m_i = 0; m_i < pts.Count; m_i++)
                {
                    int len = pts[m_i].Count;
                    if (len > 1 && pts[m_i][0].X == pts[m_i][len - 1].X &&
                        pts[m_i][0].Y == pts[m_i][len - 1].Y) len--;

                    if (len == 0 || (len < 3 && delta <= 0))
                        continue;
                    else if (len == 1)
                    {
                        Polygon arc;
                        arc = BuildArc(pts[m_i][len - 1], 0, 2 * Math.PI, delta);
                        solution.Add(arc);
                        continue;
                    }

                    //build normals ...
                    normals.Clear();
                    normals.Capacity = len;
                    for (int j = 0; j < len -1; ++j)
                        normals.Add(GetUnitNormal(pts[m_i][j], pts[m_i][j+1]));
                    normals.Add(GetUnitNormal(pts[m_i][len - 1], pts[m_i][0]));

                    currentPoly = new Polygon();
                    m_k = len - 1;
                    for (m_j = 0; m_j < len; ++m_j)
                    {
                        switch (jointype)
                        {
                            case JoinType.jtMiter:
                            {
                                m_R = 1 + (normals[m_j].X*normals[m_k].X +
                                    normals[m_j].Y*normals[m_k].Y);
                                if (m_R >= RMin) DoMiter(); else DoSquare(MiterLimit);
                                break;
                            }
                            case JoinType.jtRound:
                                DoRound();
                                break;
                            case JoinType.jtSquare:
                                DoSquare(1);
                                break;
                        }
                        m_k = m_j;
                    }
                    solution.Add(currentPoly);
                }

                //finally, clean up untidy corners ...
                Clipper clpr = new Clipper();
                clpr.AddPolygons(solution, PolyType.ptSubject);
                if (delta > 0)
                {
                    clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftPositive, PolyFillType.pftPositive);
                }
                else
                {
                    IntRect r = clpr.GetBounds();
                    Polygon outer = new Polygon(4);

                    outer.Add(new IntPoint(r.left - 10, r.bottom + 10));
                    outer.Add(new IntPoint(r.right + 10, r.bottom + 10));
                    outer.Add(new IntPoint(r.right + 10, r.top - 10));
                    outer.Add(new IntPoint(r.left - 10, r.top - 10));

                    clpr.AddPolygon(outer, PolyType.ptSubject);
                    clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftNegative, PolyFillType.pftNegative);
                    if (solution.Count > 0)
                    {
                        solution.RemoveAt(0);
                        for (int i = 0; i < solution.Count; i++)
                            solution[i].Reverse();
                    }
                }
            }
        static public PolyTree FindDistictObjectBounds(ImageBuffer image)
        {
            MarchingSquaresByte marchingSquaresData = new MarchingSquaresByte(image, 5, 0);
            marchingSquaresData.CreateLineSegments();
            Polygons lineLoops = marchingSquaresData.CreateLineLoops(1);

            if (lineLoops.Count == 1)
            {
                return null;
            }

            // create a bounding polygon to clip against
            IntPoint min = new IntPoint(long.MaxValue, long.MaxValue);
            IntPoint max = new IntPoint(long.MinValue, long.MinValue);
            foreach (Polygon polygon in lineLoops)
            {
                foreach (IntPoint point in polygon)
                {
                    min.X = Math.Min(point.X - 10, min.X);
                    min.Y = Math.Min(point.Y - 10, min.Y);
                    max.X = Math.Max(point.X + 10, max.X);
                    max.Y = Math.Max(point.Y + 10, max.Y);
                }
            }

            Polygon boundingPoly = new Polygon();
            boundingPoly.Add(min);
            boundingPoly.Add(new IntPoint(min.X, max.Y));
            boundingPoly.Add(max);
            boundingPoly.Add(new IntPoint(max.X, min.Y));

            // now clip the polygons to get the inside and outside polys
            Clipper clipper = new Clipper();
            clipper.AddPolygons(lineLoops, PolyType.ptSubject);
            clipper.AddPolygon(boundingPoly, PolyType.ptClip);

            PolyTree polyTreeForPlate = new PolyTree();
            clipper.Execute(ClipType.ctIntersection, polyTreeForPlate);

            return polyTreeForPlate;
        }
 //------------------------------------------------------------------------------
 // SimplifyPolygon functions ...
 // Convert self-intersecting polygons into simple polygons
 //------------------------------------------------------------------------------
 public static Polygons SimplifyPolygon(Polygon poly)
 {
     Polygons result = new Polygons();
     Clipper c = new Clipper();
     c.AddPolygon(poly, PolyType.ptSubject);
     c.Execute(ClipType.ctUnion, result);
     return result;
 }
Пример #5
0
        //------------------------------------------------------------------------------
        // SimplifyPolygon functions ...
        // Convert self-intersecting polygons into simple polygons
        //------------------------------------------------------------------------------

        public static Polygons SimplifyPolygon(Polygon poly, 
              PolyFillType fillType = PolyFillType.pftEvenOdd)
        {
            Polygons result = new Polygons();
            Clipper c = new Clipper();
            c.AddPolygon(poly, PolyType.ptSubject);
            c.Execute(ClipType.ctUnion, result, fillType, fillType);
            return result;
        }
Пример #6
0
            public PolyOffsetBuilder(Polygons pts, Polygons solution, double delta, 
                JoinType jointype, double MiterLimit = 2, bool AutoFix = true)
            {
                //precondtion: solution != pts

                if (delta == 0)
                {
                    solution = pts;
                    return;
                }

                this.pts = pts;
                this.delta = delta;

                //AutoFix - fixes polygon orientation if necessary and removes 
                //duplicate vertices. Can be set false when you're sure that polygon
                //orientation is correct and that there are no duplicate vertices.
                if (AutoFix)
                {
                    int Len = pts.Count, botI = 0;
                    while (botI < Len && pts[botI].Count == 0) botI++;
                    if (botI == Len) return;

                    //botPt: used to find the lowermost (in inverted Y-axis) & leftmost point
                    //This point (on pts[botI]) must be on an outer polygon ring and if 
                    //its orientation is false (counterclockwise) then assume all polygons 
                    //need reversing ...
                    IntPoint botPt = pts[botI][0];
                    for (int i = botI; i < Len; ++i)
                    {
                        if (pts[i].Count == 0) continue;
                        if (UpdateBotPt(pts[i][0], ref botPt)) botI = i;
                        for (int j = pts[i].Count -1; j > 0; j--)
                        {
                            if (PointsEqual(pts[i][j], pts[i][j -1]))
                                pts[i].RemoveAt(j);
                            else if (UpdateBotPt(pts[i][j], ref botPt))
                                botI = i;
                        }
                    }
                    if (!Orientation(pts[botI]))
                        ReversePolygons(pts);
                }

                if (MiterLimit <= 1) MiterLimit = 1;
                double RMin = 2.0 / (MiterLimit*MiterLimit);

                normals = new List<DoublePoint>();

                double deltaSq = delta*delta;
                solution.Clear();
                solution.Capacity = pts.Count;
                for (m_i = 0; m_i < pts.Count; m_i++)
                {
                    int len = pts[m_i].Count;
                    if (len > 1 && pts[m_i][0].X == pts[m_i][len - 1].X &&
                        pts[m_i][0].Y == pts[m_i][len - 1].Y) len--;

                    if (len == 0 || (len < 3 && delta <= 0)) 
                        continue;
                    else if (len == 1)
                    {
                        Polygon arc;
                        arc = BuildArc(pts[m_i][len - 1], 0, 2 * Math.PI, delta);
                        solution.Add(arc);
                        continue;
                    }

                    //build normals ...
                    normals.Clear();
                    normals.Capacity = len;
                    for (int j = 0; j < len -1; ++j)
                        normals.Add(GetUnitNormal(pts[m_i][j], pts[m_i][j+1]));
                    normals.Add(GetUnitNormal(pts[m_i][len - 1], pts[m_i][0]));

                    currentPoly = new Polygon();
                    m_k = len - 1;
                    for (m_j = 0; m_j < len; ++m_j)
                    {
                        switch (jointype)
                        {
                            case JoinType.jtMiter:
                            {
                                m_R = 1 + (normals[m_j].X*normals[m_k].X + 
                                    normals[m_j].Y*normals[m_k].Y);
                                if (m_R >= RMin) DoMiter(); else DoSquare(MiterLimit);
                                break;
                            }
                            case JoinType.jtRound: 
                                DoRound();
                                break;
                            case JoinType.jtSquare:
                                DoSquare(1);
                                break;
                        }
                        m_k = m_j;
                    }
                    solution.Add(currentPoly);
                }

                //finally, clean up untidy corners ...
                Clipper clpr = new Clipper();
                clpr.AddPolygons(solution, PolyType.ptSubject);
                if (delta > 0)
                {
                    clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftPositive, PolyFillType.pftPositive);
                }
                else
                {
                    IntRect r = clpr.GetBounds();
                    Polygon outer = new Polygon(4);

                    outer.Add(new IntPoint(r.left - 10, r.bottom + 10));
                    outer.Add(new IntPoint(r.right + 10, r.bottom + 10));
                    outer.Add(new IntPoint(r.right + 10, r.top - 10));
                    outer.Add(new IntPoint(r.left - 10, r.top - 10));

                    clpr.AddPolygon(outer, PolyType.ptSubject);
                    clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftNegative, PolyFillType.pftNegative);
                    if (solution.Count > 0)
                    {
                        solution.RemoveAt(0);
                        for (int i = 0; i < solution.Count; i++)
                            solution[i].Reverse();
                    }
                }
            }
Пример #7
0
            //------------------------------------------------------------------------------
            public PolyOffsetBuilder(Polygons pts, Polygons solution, bool isPolygon, double delta,
                JoinType jointype, EndType endtype, double limit = 0)
            {
                //precondition: solution != pts

                if (delta == 0) { solution = pts; return; }
                m_p = pts;
                m_delta = delta;
                m_rmin = 0.5;

                if (jointype == JoinType.jtMiter)
                {
                    if (limit > 2) m_rmin = 2.0 / (limit * limit);
                    limit = 0.25; //just in case endtype == etRound
                }
                else
                {
                    if (limit <= 0) limit = 0.25;
                    else if (limit > Math.Abs(delta)) limit = Math.Abs(delta);
                }

                double deltaSq = delta * delta;
                solution.Clear();
                solution.Capacity = pts.Count;
                for (m_i = 0; m_i < pts.Count; m_i++)
                {
                    int len = pts[m_i].Count;
                    if (len == 0 || (len < 3 && delta <= 0))
                        continue;
                    else if (len == 1)
                    {
                        currentPoly = new Polygon();
                        currentPoly = BuildArc(pts[m_i][0], 0, 2 * Math.PI, delta, limit);
                        solution.Add(currentPoly);
                        continue;
                    }

                    bool forceClose = PointsEqual(pts[m_i][0], pts[m_i][len - 1]);
                    if (forceClose) len--;

                    //build normals ...
                    normals.Clear();
                    normals.Capacity = len;
                    for (int j = 0; j < len - 1; ++j)
                        normals.Add(GetUnitNormal(pts[m_i][j], pts[m_i][j + 1]));
                    if (isPolygon || forceClose)
                        normals.Add(GetUnitNormal(pts[m_i][len - 1], pts[m_i][0]));
                    else
                        normals.Add(new DoublePoint(normals[len - 2]));

                    currentPoly = new Polygon();
                    if (isPolygon || forceClose)
                    {
                        m_k = len - 1;
                        for (m_j = 0; m_j < len; ++m_j)
                            OffsetPoint(jointype, limit);
                        solution.Add(currentPoly);
                        if (!isPolygon)
                        {
                            currentPoly = new Polygon();
                            m_delta = -m_delta;
                            m_k = len - 1;
                            for (m_j = 0; m_j < len; ++m_j)
                                OffsetPoint(jointype, limit);
                            m_delta = -m_delta;
                            currentPoly.Reverse();
                            solution.Add(currentPoly);
                        }
                    }
                    else
                    {
                        m_k = 0;
                        for (m_j = 1; m_j < len - 1; ++m_j)
                            OffsetPoint(jointype, limit);

                        IntPoint pt1;
                        if (endtype == EndType.etButt)
                        {
                            m_j = len - 1;
                            pt1 = new IntPoint((Int64)Round(pts[m_i][m_j].X + normals[m_j].X *
                              delta), (Int64)Round(pts[m_i][m_j].Y + normals[m_j].Y * delta));
                            AddPoint(pt1);
                            pt1 = new IntPoint((Int64)Round(pts[m_i][m_j].X - normals[m_j].X *
                              delta), (Int64)Round(pts[m_i][m_j].Y - normals[m_j].Y * delta));
                            AddPoint(pt1);
                        }
                        else
                        {
                            m_j = len - 1;
                            m_k = len - 2;
                            normals[m_j].X = -normals[m_j].X;
                            normals[m_j].Y = -normals[m_j].Y;
                            if (endtype == EndType.etSquare) DoSquare();
                            else DoRound(limit);
                        }

                        //re-build Normals ...
                        for (int j = len - 1; j > 0; j--)
                        {
                            normals[j].X = -normals[j - 1].X;
                            normals[j].Y = -normals[j - 1].Y;
                        }
                        normals[0].X = -normals[1].X;
                        normals[0].Y = -normals[1].Y;

                        m_k = len - 1;
                        for (m_j = m_k - 1; m_j > 0; --m_j)
                            OffsetPoint(jointype, limit);

                        if (endtype == EndType.etButt)
                        {
                            pt1 = new IntPoint((Int64)Round(pts[m_i][0].X - normals[0].X * delta),
                              (Int64)Round(pts[m_i][0].Y - normals[0].Y * delta));
                            AddPoint(pt1);
                            pt1 = new IntPoint((Int64)Round(pts[m_i][0].X + normals[0].X * delta),
                              (Int64)Round(pts[m_i][0].Y + normals[0].Y * delta));
                            AddPoint(pt1);
                        }
                        else
                        {
                            m_k = 1;
                            if (endtype == EndType.etSquare) DoSquare();
                            else DoRound(limit);
                        }
                        solution.Add(currentPoly);
                    }
                }

                //finally, clean up untidy corners ...
                Clipper clpr = new Clipper();
                clpr.AddPolygons(solution, PolyType.ptSubject);
                if (delta > 0)
                {
                    clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftPositive, PolyFillType.pftPositive);
                }
                else
                {
                    IntRect r = clpr.GetBounds();
                    Polygon outer = new Polygon(4);

                    outer.Add(new IntPoint(r.left - 10, r.bottom + 10));
                    outer.Add(new IntPoint(r.right + 10, r.bottom + 10));
                    outer.Add(new IntPoint(r.right + 10, r.top - 10));
                    outer.Add(new IntPoint(r.left - 10, r.top - 10));

                    clpr.AddPolygon(outer, PolyType.ptSubject);
                    clpr.ReverseSolution = true;
                    clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftNegative, PolyFillType.pftNegative);
                    if (solution.Count > 0) solution.RemoveAt(0);
                }
            }
Пример #8
0
        public string TranslateGerber( string path )
        {
            String output = "";

            PointF pstart = new PointF(0, 0);
            PointF pend = new PointF(0, 0);

            Double x, y;
            int d;

            Regex reXYLine = new Regex(@"^X(\d+)Y(\d+)D(\d\d)\*$");
            Regex reFSLA = new Regex(@"%FSLAX(\d)(\d)Y(\d)(\d)\*%");
            Regex reApDef = new Regex(@"%ADD(\d+)R,([\d\.]+)X([\d\.]+)\*%");
            Regex reApGroup = new Regex(@"^D(\d+)\*$");

            List<string> fileLines = new List<string>();

            StreamReader srt;

            List<LineF> lines = new List<LineF>();

            // read the border file
            if (null != path)
            {
                srt = new StreamReader(path);
                while (true)
                {
                    string line = srt.ReadLine();
                    if (null == line) break;
                    fileLines.Add(line);
                }
                srt.Close();
            }

            int decimal_x = 4, decimal_y = 4;
            double mul_x = Math.Pow(10, decimal_x);
            double mul_y = Math.Pow(10, decimal_y);

            foreach (string line in fileLines)
            {
                // format is 2.4 (CHECK?)
                //string line = srt.ReadLine();
                //if (null == line) break;

                Match m = reFSLA.Match(line);
                if (m.Success)
                {
                    Group group = m.Groups[2];
                    CaptureCollection cc = group.Captures;
                    decimal_x = Int32.Parse(cc[0].Value);

                    group = m.Groups[4];
                    cc = group.Captures;
                    decimal_y = Int32.Parse(cc[0].Value);
                    mul_x = Math.Pow(10, decimal_x);
                    mul_y = Math.Pow(10, decimal_y);

                }

                m = reXYLine.Match(line);
                if (m.Success)
                {

                    Group group = m.Groups[1];
                    CaptureCollection cc = group.Captures;
                    //x = Double.Parse(cc[0].Value) / 10000 * INMM; // *dscale;
                    x = Double.Parse(cc[0].Value) / mul_x * INMM; // *dscale;

                    group = m.Groups[2];
                    cc = group.Captures;
                    //y = Double.Parse(cc[0].Value) / 10000 * INMM; // *dscale;
                    y = Double.Parse(cc[0].Value) / mul_y * INMM; // *dscale;

                    group = m.Groups[3];
                    cc = group.Captures;
                    d = Int32.Parse(cc[0].Value);

                    // D02 is move, D01 is line...
                    if (d == 2 || d == 1)
                    {
                        if (x > maxx) maxx = x;
                        if (y > maxy) maxy = y;
                        if (x < minx) minx = x;
                        if (y < miny) miny = y;
                    }
                }
            }

            xrange = maxx - minx;
            yrange = maxy - miny;

            List<Aperture> apertures = new List<Aperture>();

            string ee = Path.GetExtension(path).ToUpper();

            if (Path.GetExtension(path).ToUpper().Equals(".DRD"))
            {
                readDrills(fileLines, out apertures, ref maxx, ref maxy, ref minx, ref miny);

                output += ("// Excellon (drill) file: " + Path.GetFileName(path) + "\r\n\r\n");

                foreach (Aperture ap in apertures)
                {
                    output += string.Format("\tcircle {0:00.00}, {1:00.00}, {2:00.00}\r\n",
                        ap.border.Left + ap.border.Width / 2,
                        ap.border.Top + ap.border.Height / 2,
                        ap.CircleDiameter ); // ap.border.Width );
                }

                return output ;
            }
            else readApertures(fileLines, out apertures, out lines, ref maxx, ref maxy, ref minx, ref miny);

            // now create a set of polygons that we can clip...

            Polygons polys = new Polygons();

            foreach (LineF line in lines)
            {
                // Console.WriteLine("Line: width is " + line.width);

                // circle at start, end
                polys.Add(ListToPoly(CircleToPoints(line.start, line.width)));
                polys.Add(ListToPoly(CircleToPoints(line.end, line.width)));

                // tangent lines? here, a rectangle
                Polygon rect = new Polygon();

                LineF lf1 = line.shift(90, line.width / 2);
                LineF lf2 = line.shift(-90, line.width / 2);

                rect.Add(new IntPoint((long)(lf1.start.X * SCALE), (long)(lf1.start.Y * SCALE)));
                rect.Add(new IntPoint((long)(lf1.end.X * SCALE), (long)(lf1.end.Y * SCALE)));
                rect.Add(new IntPoint((long)(lf2.end.X * SCALE), (long)(lf2.end.Y * SCALE)));
                rect.Add(new IntPoint((long)(lf2.start.X * SCALE), (long)(lf2.start.Y * SCALE)));

                polys.Add(rect);

            }

            foreach (Aperture ap in apertures)
            {
                if (ap.CircleDiameter > 0)
                {
                    polys.Add(ListToPoly(CircleToPoints(ap)));
                }
                else
                {
                    Polygon rect = new Polygon();
                    rect.Add(new IntPoint((long)(ap.border.Left * SCALE), (long)(ap.border.Top * SCALE)));
                    rect.Add(new IntPoint((long)(ap.border.Right * SCALE), (long)(ap.border.Top * SCALE)));
                    rect.Add(new IntPoint((long)(ap.border.Right * SCALE), (long)(ap.border.Bottom * SCALE)));
                    rect.Add(new IntPoint((long)(ap.border.Left * SCALE), (long)(ap.border.Bottom * SCALE)));
                    polys.Add(rect);
                }
            }

            Polygons solution = new Polygons ();

            Clipper clip = new Clipper();
            //foreach (Polygon poly in polys)
            for( int i = 0; i< polys.Count; i++ )
            {
                Polygon poly = polys[i];
                if (!Clipper.Orientation(poly)) poly.Reverse();
                clip.AddPolygon(poly, PolyType.ptSubject);
            }
            //clip.AddPolygons(polys, PolyType.ptSubject);
            clip.Execute(ClipType.ctUnion, solution, PolyFillType.pftNonZero, PolyFillType.pftNonZero);

            polys = solution;
            // let's look at this ...

            output += ("// Gerber file: " + Path.GetFileName( path ) + "\r\n\r\n");

            {
                //DXF.DxfDocument doc = new DXF.DxfDocument();
                foreach (Polygon poly in polys)
                {
                    for (int i = 1; i < poly.Count; i++)
                    {
                        /*
                        doc.AddEntity(new DXF.Entities.Line(
                                new DXF.Vector2(poly[i - 1].X / (double)SCALE, poly[i - 1].Y / (double)SCALE),
                                new DXF.Vector2(poly[i ].X / (double)SCALE, poly[i ].Y / (double)SCALE)
                            ));
                        */

                        output += string.Format("\tline {0:00.00}, {1:00.00}, {2:00.00}, {3:00.00}\r\n",
                            poly[i - 1].X / (double)SCALE, poly[i - 1].Y / (double)SCALE,
                            poly[i].X / (double)SCALE, poly[i].Y / (double)SCALE);

                    }
                    /*
                    doc.AddEntity(new DXF.Entities.Line(
                            new DXF.Vector2(poly[poly.Count - 1].X / (double)SCALE, poly[poly.Count - 1].Y / (double)SCALE),
                            new DXF.Vector2(poly[0].X / (double)SCALE, poly[0].Y / (double)SCALE)
                        ));
                    */

                    output += string.Format("\tline {0:00.00}, {1:00.00}, {2:00.00}, {3:00.00}\r\n",
                        poly[poly.Count - 1].X / (double)SCALE, poly[poly.Count - 1].Y / (double)SCALE,
                        poly[0].X / (double)SCALE, poly[0].Y / (double)SCALE);

                }

                return output;

                /**
                // add a bounding box...

                doc.AddEntity(new DXF.Entities.Line(new DXF.Vector2(minx, miny), new DXF.Vector2(maxx, miny)));
                doc.AddEntity(new DXF.Entities.Line(new DXF.Vector2(maxx, miny), new DXF.Vector2(maxx, maxy)));
                doc.AddEntity(new DXF.Entities.Line(new DXF.Vector2(maxx, maxy), new DXF.Vector2(minx, maxy)));
                doc.AddEntity(new DXF.Entities.Line(new DXF.Vector2(minx, maxy), new DXF.Vector2(minx, miny)));
                **/

                // add a reference at (0,0)

                //doc.AddEntity(new DXF.Entities.Line(new DXF.Vector2( -5, 5 ), new DXF.Vector2(  5, -5 )));
                //doc.AddEntity(new DXF.Entities.Line(new DXF.Vector2(  5, 5 ), new DXF.Vector2( -5, -5 )));

                //doc.Save(outputPath, DXF.Header.DxfVersion.AutoCad2000);

            }

            /*
            // readDrills(drillFileLines, out drillApertures, ref maxx, ref maxy, ref minx, ref miny);

            DXF.DxfDocument doc = new DXF.DxfDocument();

            foreach (LineF line in lines)
            {
                Console.WriteLine("Line: width is " + line.width);

                // circle at start, end
                doc.AddEntity(new DXF.Entities.Circle(new DXF.Vector2(line.start.X, line.start.Y), line.width / 2));
                doc.AddEntity(new DXF.Entities.Circle(new DXF.Vector2(line.end.X, line.end.Y), line.width / 2));

                // tangent lines?

                LineF lf1 = line.shift(90, line.width / 2);
                doc.AddEntity(new DXF.Entities.Line(new DXF.Vector2(lf1.start.X, lf1.start.Y), new DXF.Vector2(lf1.end.X, lf1.end.Y)));
                LineF lf2 = line.shift(-90, line.width / 2);
                doc.AddEntity(new DXF.Entities.Line(new DXF.Vector2(lf2.start.X, lf2.start.Y), new DXF.Vector2(lf2.end.X, lf2.end.Y)));

                // doc.AddEntity(new DXF.Entities.Line(new DXF.Vector2(line.start.X, line.start.Y), new DXF.Vector2(line.end.X, line.end.Y)));
            }

            foreach (Aperture ap in apertures)
            {
                if (ap.CircleDiameter > 0)
                {
                    double half = ap.border.Width/2;
                    doc.AddEntity( new DXF.Entities.Circle( new DXF.Vector2( ap.border.Left + half, ap.border.Top + half ), ap.border.Width/2 ));

                    Console.WriteLine("ap circle");

                }
                else
                {
                    // rectangle in 4 lines...

                    doc.AddEntity(new DXF.Entities.Line(new DXF.Vector2(ap.border.Left, ap.border.Top), new DXF.Vector2(ap.border.Right, ap.border.Top)));
                    doc.AddEntity(new DXF.Entities.Line(new DXF.Vector2(ap.border.Left, ap.border.Bottom), new DXF.Vector2(ap.border.Right, ap.border.Bottom)));
                    doc.AddEntity(new DXF.Entities.Line(new DXF.Vector2(ap.border.Left, ap.border.Top), new DXF.Vector2(ap.border.Left, ap.border.Bottom)));
                    doc.AddEntity(new DXF.Entities.Line(new DXF.Vector2(ap.border.Right, ap.border.Top), new DXF.Vector2(ap.border.Right, ap.border.Bottom)));

                    Console.WriteLine("ap rectangle");

                }
            }

            doc.Save(outputPath, DXF.Header.DxfVersion.AutoCad2000 );
            */
        }
Пример #9
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)
                {
                }
            }
        }