コード例 #1
0
        public static List <NestPath> polygonOffset(NestPath polygon, double offset)
        {
            List <NestPath> result = new List <NestPath>();

            if (offset == 0 || GeometryUtil.almostEqual(offset, 0))
            {
                /**
                 * return EmptyResult
                 */
                return(result);
            }
            Path p = new Path();

            foreach (Segment s in polygon.getSegments())
            {
                ClipperCoor cc = toClipperCoor(s.getX(), s.getY());
                p.Add(new IntPoint(cc.getX(), cc.getY()));
            }

            int           miterLimit = 2;
            ClipperOffset co         = new ClipperOffset(miterLimit, Config.CURVE_TOLERANCE * Config.CLIIPER_SCALE);

            co.AddPath(p, JoinType.jtRound, EndType.etClosedPolygon);

            Paths newpaths = new Paths();

            co.Execute(ref newpaths, offset * Config.CLIIPER_SCALE);


            /**
             * 这里的length是1的话就是我们想要的
             */
            for (int i = 0; i < newpaths.Count; i++)
            {
                result.Add(CommonUtil.clipperToNestPath(newpaths[i]));
            }

            if (offset > 0)
            {
                NestPath from = result[0];
                if (GeometryUtil.polygonArea(from) > 0)
                {
                    from.reverse();
                }
                from.add(from.get(0)); from.getSegments().RemoveAt(0);
            }


            return(result);
        }
コード例 #2
0
        public static List <String> svgGenerator(List <NestPath> list, List <List <Placement> > applied, double binwidth, double binHeight)
        {
            List <String> strings = new List <String>();
            int           x       = 10;
            int           y       = 0;

            foreach (List <Placement> binlist in applied)
            {
                String s = " <g transform=\"translate(" + x + "  " + y + ")\">" + "\n";
                s += "    <rect x=\"0\" y=\"0\" width=\"" + binwidth + "\" height=\"" + binHeight + "\"  fill=\"none\" stroke=\"#010101\" stroke-width=\"1\" />\n";
                foreach (Placement placement in binlist)
                {
                    int      bid      = placement.bid;
                    NestPath nestPath = getNestPathByBid(bid, list);
                    double   ox       = placement.translate.x;
                    double   oy       = placement.translate.y;
                    double   rotate   = placement.rotate;
                    s += "<g transform=\"translate(" + ox + x + " " + oy + y + ") rotate(" + rotate + ")\"> \n";
                    s += "<path d=\"";
                    for (int i = 0; i < nestPath.getSegments().Count; i++)
                    {
                        if (i == 0)
                        {
                            s += "M";
                        }
                        else
                        {
                            s += "L";
                        }
                        Segment segment = nestPath.get(i);
                        s += segment.x + " " + segment.y + " ";
                    }
                    s += "Z\" fill=\"#8498d1\" stroke=\"#010101\" stroke-width=\"1\" />" + " \n";
                    s += "</g> \n";
                }
                s += "</g> \n";
                y += (int)(binHeight + 50);
                strings.Add(s);
            }
            return(strings);
        }
コード例 #3
0
        /**
         * 根据板件列表与旋转角列表,通过nfp,计算板件在底板上的位置,并返回这个种群的fitness
         * @param paths
         * @return
         */
        public Result placePaths(List <NestPath> paths)
        {
            List <NestPath> rotated = new List <NestPath>();

            for (int i = 0; i < paths.Count; i++)
            {
                NestPath r = GeometryUtil.rotatePolygon2Polygon(paths[i], paths[i].getRotation());
                r.setRotation(paths[i].getRotation());
                r.setSource(paths[i].getSource());
                r.setId(paths[i].getId());
                rotated.Add(r);
            }
            paths = rotated;

            List <List <Vector> > allplacements = new List <List <Vector> >();
            double          fitness             = 0;
            double          binarea             = Math.Abs(GeometryUtil.polygonArea(this.binPolygon));
            String          key = null;
            List <NestPath> nfp = null;

            while (paths.Count > 0)
            {
                List <NestPath> placed     = new List <NestPath>();
                List <Vector>   placements = new List <Vector>();

                fitness += 1;
                double minwidth = Double.MaxValue;
                for (int i = 0; i < paths.Count; i++)
                {
                    NestPath path = paths[i];

                    //inner NFP
                    key = new JavaScriptSerializer().Serialize(new NfpKey(-1, path.getId(), true, 0, path.getRotation()));

                    //key = gson.toJson(new NfpKey(-1, path.getId(), true, 0, path.getRotation()));

                    if (!nfpCache.ContainsKey(key))
                    {
                        continue;
                    }

                    List <NestPath> binNfp = nfpCache[key];



                    // ensure exists
                    bool error = false;
                    for (int j = 0; j < placed.Count; j++)
                    {
                        key = new JavaScriptSerializer().Serialize(new NfpKey(placed[j].getId(), path.getId(), false, placed[j].getRotation(), path.getRotation()));
                        // key = gson.toJson(new NfpKey(placed[j].getId(), path.getId(), false, placed[j].getRotation(), path.getRotation()));
                        if (nfpCache.ContainsKey(key))
                        {
                            nfp = nfpCache[key];
                        }
                        else
                        {
                            error = true;
                            break;
                        }
                    }
                    if (error)
                    {
                        continue;
                    }


                    Vector position = null;
                    if (placed.Count == 0)
                    {
                        // first placement , put it on the lefth
                        for (int j = 0; j < binNfp.Count; j++)
                        {
                            for (int k = 0; k < binNfp[j].size(); k++)
                            {
                                if (position == null || binNfp[j].get(k).x - path.get(0).x < position.x)
                                {
                                    position = new Vector(
                                        binNfp[j].get(k).x - path.get(0).x,
                                        binNfp[j].get(k).y - path.get(0).y,
                                        path.getId(),
                                        path.getRotation()
                                        );
                                }
                            }
                        }
                        placements.Add(position);
                        placed.Add(path);
                        continue;
                    }

                    Paths clipperBinNfp = new Paths();

                    for (int j = 0; j < binNfp.Count; j++)
                    {
                        NestPath binNfpj = binNfp[j];
                        clipperBinNfp.Add(scaleUp2ClipperCoordinates(binNfpj));
                    }
                    Clipper clipper     = new Clipper();
                    Paths   combinedNfp = new Paths();


                    for (int j = 0; j < placed.Count; j++)
                    {
                        key = new JavaScriptSerializer().Serialize(new NfpKey(placed[j].getId(), path.getId(), false, placed[j].getRotation(), path.getRotation()));
                        //key = gson.toJson(new NfpKey(placed[j].getId(), path.getId(), false, placed[j].getRotation(), path.getRotation()));
                        nfp = nfpCache[key];
                        if (nfp == null)
                        {
                            continue;
                        }

                        for (int k = 0; k < nfp.Count; k++)
                        {
                            Path clone = PlacementWorker.scaleUp2ClipperCoordinates(nfp[k]);
                            for (int m = 0; m < clone.Count; m++)
                            {
                                long     clx      = (long)clone[m].X;
                                long     cly      = (long)clone[m].Y;
                                IntPoint intPoint = clone[m];
                                intPoint.X = (clx + (long)(placements[j].x * Config.CLIIPER_SCALE));
                                intPoint.Y = (cly + (long)(placements[j].y * Config.CLIIPER_SCALE));
                                clone[m]   = intPoint;
                            }
                            //clone = clone.Cleaned(0.0001 * Config.CLIIPER_SCALE);
                            clone = Clipper.CleanPolygon(clone, 0.0001 * Config.CLIIPER_SCALE);
                            double areaPoly = Math.Abs(Clipper.Area(clone));
                            if (clone.Count > 2 && areaPoly > 0.1 * Config.CLIIPER_SCALE * Config.CLIIPER_SCALE)
                            {
                                clipper.AddPath(clone, PolyType.ptSubject, true);
                            }
                        }
                    }
                    if (!clipper.Execute(ClipType.ctUnion, combinedNfp, PolyFillType.pftNonZero, PolyFillType.pftNonZero))
                    {
                        continue;
                    }

                    //difference with bin polygon
                    Paths finalNfp = new Paths();
                    clipper = new Clipper();

                    clipper.AddPaths(combinedNfp, PolyType.ptClip, true);
                    clipper.AddPaths(clipperBinNfp, PolyType.ptSubject, true);
                    if (!clipper.Execute(ClipType.ctDifference, finalNfp, PolyFillType.pftNonZero, PolyFillType.pftNonZero))
                    {
                        continue;
                    }

                    // finalNfp = finalNfp.Cleaned(0.0001 * Config.CLIIPER_SCALE);
                    finalNfp = Clipper.CleanPolygons(finalNfp, 0.0001 * Config.CLIIPER_SCALE);
                    for (int j = 0; j < finalNfp.Count(); j++)
                    {
                        //double areaPoly = Math.Abs(finalNfp[j].Area);
                        double areaPoly = Math.Abs(Clipper.Area(finalNfp[j]));
                        if (finalNfp[j].Count < 3 || areaPoly < 0.1 * Config.CLIIPER_SCALE * Config.CLIIPER_SCALE)
                        {
                            finalNfp.RemoveAt(j);
                            j--;
                        }
                    }

                    if (finalNfp == null || finalNfp.Count == 0)
                    {
                        continue;
                    }

                    List <NestPath> f = new List <NestPath>();
                    for (int j = 0; j < finalNfp.Count; j++)
                    {
                        f.Add(toNestCoordinates(finalNfp[j]));
                    }

                    List <NestPath> finalNfpf  = f;
                    double          minarea    = Double.MinValue;
                    double          minX       = Double.MaxValue;
                    NestPath        nf         = null;
                    double          area       = Double.MinValue;
                    Vector          shifvector = null;
                    for (int j = 0; j < finalNfpf.Count; j++)
                    {
                        nf = finalNfpf[j];
                        if (Math.Abs(GeometryUtil.polygonArea(nf)) < 2)
                        {
                            continue;
                        }
                        for (int k = 0; k < nf.size(); k++)
                        {
                            NestPath allpoints = new NestPath();
                            for (int m = 0; m < placed.Count; m++)
                            {
                                for (int n = 0; n < placed[m].size(); n++)
                                {
                                    allpoints.add(new Segment(placed[m].get(n).x + placements[m].x,
                                                              placed[m].get(n).y + placements[m].y));
                                }
                            }
                            shifvector = new Vector(nf.get(k).x - path.get(0).x, nf.get(k).y - path.get(0).y, path.getId(), path.getRotation(), combinedNfp);
                            for (int m = 0; m < path.size(); m++)
                            {
                                allpoints.add(new Segment(path.get(m).x + shifvector.x, path.get(m).y + shifvector.y));
                            }
                            Bound rectBounds = GeometryUtil.getPolygonBounds(allpoints);

                            area = rectBounds.getWidth() * 2 + rectBounds.getHeight();
                            if (minarea == Double.MinValue ||
                                area < minarea ||
                                (GeometryUtil.almostEqual(minarea, area) &&
                                 (minX == Double.MinValue || shifvector.x < minX)))
                            {
                                minarea  = area;
                                minwidth = rectBounds.getWidth();
                                position = shifvector;
                                minX     = shifvector.x;
                            }
                        }
                    }
                    if (position != null)
                    {
                        placed.Add(path);
                        placements.Add(position);
                    }
                }
                if (minwidth != Double.MinValue)
                {
                    fitness += minwidth / binarea;
                }



                for (int i = 0; i < placed.Count; i++)
                {
                    int index = paths.IndexOf(placed[i]);
                    if (index >= 0)
                    {
                        paths.RemoveAt(index);
                    }
                }

                if (placements != null && placements.Count > 0)
                {
                    allplacements.Add(placements);
                }
                else
                {
                    break; // something went wrong
                }
            }
            // there were paths that couldn't be placed
            fitness += 2 * paths.Count;
            return(new Result(allplacements, fitness, paths, binarea));
        }
コード例 #4
0
        /**
         *  开始进行Nest计算
         * @return
         */
        public List <List <Placement> > startNest()
        {
            List <NestPath> tree = CommonUtil.BuildTree(parts, Config.CURVE_TOLERANCE);

            CommonUtil.offsetTree(tree, 0.5 * config.SPACING);
            binPath.config = config;
            foreach (NestPath nestPath in parts)
            {
                nestPath.config = config;
            }
            NestPath binPolygon = NestPath.cleanNestPath(binPath);
            Bound    binBound   = GeometryUtil.getPolygonBounds(binPolygon);

            if (config.SPACING > 0)
            {
                List <NestPath> offsetBin = CommonUtil.polygonOffset(binPolygon, -0.5 * config.SPACING);
                if (offsetBin.Count == 1)
                {
                    binPolygon = offsetBin[0];
                }
            }
            binPolygon.setId(-1);

            List <int>      integers = checkIfCanBePlaced(binPolygon, tree);
            List <NestPath> safeTree = new List <NestPath>();

            foreach (int i in integers)
            {
                safeTree.Add(tree[i]);
            }
            tree = safeTree;

            double xbinmax = binPolygon.get(0).x;
            double xbinmin = binPolygon.get(0).x;
            double ybinmax = binPolygon.get(0).y;
            double ybinmin = binPolygon.get(0).y;

            for (int i = 1; i < binPolygon.size(); i++)
            {
                if (binPolygon.get(i).x > xbinmax)
                {
                    xbinmax = binPolygon.get(i).x;
                }
                else if (binPolygon.get(i).x < xbinmin)
                {
                    xbinmin = binPolygon.get(i).x;
                }

                if (binPolygon.get(i).y > ybinmax)
                {
                    ybinmax = binPolygon.get(i).y;
                }
                else if (binPolygon.get(i).y < ybinmin)
                {
                    ybinmin = binPolygon.get(i).y;
                }
            }
            for (int i = 0; i < binPolygon.size(); i++)
            {
                binPolygon.get(i).x -= xbinmin;
                binPolygon.get(i).y -= ybinmin;
            }


            double binPolygonWidth  = xbinmax - xbinmin;
            double binPolygonHeight = ybinmax - ybinmin;

            if (GeometryUtil.polygonArea(binPolygon) > 0)
            {
                binPolygon.reverse();
            }

            /**
             * 确保为逆时针
             */
            for (int i = 0; i < tree.Count; i++)
            {
                Segment start = tree[i].get(0);
                Segment end   = tree[i].get(tree[i].size() - 1);
                if (start == end || GeometryUtil.almostEqual(start.x, end.x) && GeometryUtil.almostEqual(start.y, end.y))
                {
                    tree[i].pop();
                }
                if (GeometryUtil.polygonArea(tree[i]) > 0)
                {
                    tree[i].reverse();
                }
            }

            launchcount = 0;
            Result best = null;


            // Tree Modification based on nest4J
            //List<NestPath> modifiedTree = new List<NestPath>();

            //for (int i = 0; i < tree.Count; i++)
            //{
            //    List<Segment> modifiedSegment = new List<Segment>();
            //    NestPath currentTree = tree[i];
            //    List<Segment> currentTreeSegments = currentTree.getSegments();
            //    modifiedSegment.Add(currentTreeSegments[currentTreeSegments.Count-1]);
            //    for (int j = 0; j < currentTreeSegments.Count-1; j++)
            //    {
            //        modifiedSegment.Add(currentTreeSegments[j]);
            //    }
            //    currentTree.setSegments(modifiedSegment);
            //    modifiedTree.Add(currentTree);
            //}
            //tree = modifiedTree;



            for (int i = 0; i < loopCount; i++)
            {
                Result result = launchWorkers(tree, binPolygon, config);

                if (i == 0)
                {
                    best = result;
                }
                else
                {
                    if (best.fitness > result.fitness)
                    {
                        best = result;
                    }
                }
            }
            double sumarea   = 0;
            double totalarea = 0;

            for (int i = 0; i < best.placements.Count; i++)
            {
                totalarea += Math.Abs(GeometryUtil.polygonArea(binPolygon));
                for (int j = 0; j < best.placements[i].Count; j++)
                {
                    try
                    {
                        sumarea += Math.Abs(GeometryUtil.polygonArea(tree[best.placements[i][j].id]));
                    }
                    catch (Exception ex)
                    {
                    }
                }
            }
            double rate = (sumarea / totalarea) * 100;
            List <List <Placement> > appliedPlacement = applyPlacement(best, tree);

            return(appliedPlacement);
        }