Пример #1
0
        /**
         * 在遗传算法中每次突变或者是交配产生出新的种群时,可能会出现板件与旋转角度不适配的结果,需要重新检查并适配。
         * @param binPolygon
         * @param tree
         * @return
         */
        private static List <int> checkIfCanBePlaced(NestPath binPolygon, List <NestPath> tree)
        {
            List <int> CanBePlacdPolygonIndex = new List <int>();
            Bound      binBound = GeometryUtil.getPolygonBounds(binPolygon);

            for (int i = 0; i < tree.Count; i++)
            {
                NestPath nestPath = tree[i];
                if (nestPath.getRotation() == 0)
                {
                    Bound bound = GeometryUtil.getPolygonBounds(nestPath);
                    if (bound.width < binBound.width && bound.height < binBound.height)
                    {
                        CanBePlacdPolygonIndex.Add(i);
                        continue;
                    }
                }
                else
                {
                    for (int j = 0; j < nestPath.getRotation(); j++)
                    {
                        Bound rotatedBound = GeometryUtil.rotatePolygon(nestPath, (360 / nestPath.getRotation()) * j);
                        if (rotatedBound.width < binBound.width && rotatedBound.height < binBound.height)
                        {
                            CanBePlacdPolygonIndex.Add(i);
                            break;
                        }
                    }
                }
            }
            return(CanBePlacdPolygonIndex);
        }
        /**
         * 为一个polygon 返回一个角度
         * @param part
         * @return
         */
        private double randomAngle(NestPath part)
        {
            List <double> angleList = new List <double>();
            double        rotate    = Math.Max(1, part.getRotation());

            if (rotate == 0)
            {
                angleList.Add(0);
            }
            else
            {
                for (int i = 0; i < rotate; i++)
                {
                    angleList.Add((360 / rotate) * i);
                }
            }
            //打乱角度列表的排序
            angleList.Shuffle();
            //Collections.shuffle(angleList);
            for (int i = 0; i < angleList.Count; i++)
            {
                Bound rotatedPart = GeometryUtil.rotatePolygon(part, angleList[i]);
                if (rotatedPart.getWidth() < binBounds.getWidth() && rotatedPart.getHeight() < binBounds.getHeight())
                {
                    return(angleList[i]);
                }
            }

            /**
             * 没有找到合法的角度
             */
            return(-1);
        }
Пример #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
        /**
         *  一次迭代计算
         * @param tree  板件列表(去掉了带孔的多边形内孔的点集)
         * @param binPolygon    底板
         * @param config    设置
         * @return
         */
        public Result launchWorkers(List <NestPath> tree, NestPath binPolygon, Config config)
        {
            launchcount++;
            if (GA == null)
            {
                List <NestPath> adam = new List <NestPath>();
                foreach (var nestPath in tree)
                {
                    var clone = new NestPath(nestPath);
                    adam.Add(clone);
                }
                foreach (NestPath nestPath in adam)
                {
                    nestPath.area = GeometryUtil.polygonArea(nestPath);
                }
                //按零件的面积由大到小排序
                adam.Sort((x, y) => x.area.CompareTo(y.area));
                //Collections.sort(adam);
                GA = new GeneticAlgorithm(adam, binPolygon, config);
            }

            Individual individual = null;

            for (int i = 0; i < GA.population.Count; i++)
            {
                if (GA.population[i].getFitness() < 0)
                {
                    individual = GA.population[i];
                    break;
                }
            }
            //        if(individual == null ){
            //            GA.generation();
            //            individual = GA.population.get(1);
            //        }
            if (launchcount > 1 && individual == null)
            {
                GA.generation();
                individual = GA.population[1];
            }

            // 以上为GA

            List <NestPath> placelist = individual.getPlacement();
            List <double>   rotations = individual.getRotation();

            List <int> ids = new List <int>();

            for (int i = 0; i < placelist.Count; i++)
            {
                ids.Add(placelist[i].getId());
                placelist[i].setRotation(rotations[i]);
            }
            List <NfpPair> nfpPairs = new List <NfpPair>();
            NfpKey         key      = null;

            /**
             * 如果在nfpCache里没找到nfpKey 则添加进nfpPairs
             */
            for (int i = 0; i < placelist.Count; i++)
            {
                NestPath part = placelist[i];
                //这个是零件和底板之间形成的nfp,所以inside这个参数为true
                key = new NfpKey(binPolygon.getId(), part.getId(), true, 0, part.getRotation());
                if (!nfpCache.ContainsKey(serialize.Serialize(key)))
                {
                    nfpPairs.Add(new NfpPair(binPolygon, part, key));
                }
                else
                {
                }

                //这个是零件之间相互形成的nfp,所以inside这个参数为false
                for (int j = 0; j < i; j++)
                {
                    NestPath placed = placelist[j];
                    NfpKey   keyed  = new NfpKey(placed.getId(), part.getId(), false, rotations[j], rotations[i]);
                    nfpPairs.Add(new NfpPair(placed, part, keyed));
                }
            }


            /**
             * 第一次nfpCache为空 ,nfpCache存的是nfpKey所对应的两个polygon所形成的Nfp( List<NestPath> )
             */
            List <ParallelData> generatedNfp = new List <ParallelData>();

            foreach (NfpPair nfpPair in nfpPairs)
            {
                ParallelData dataTemp = NfpUtil.nfpGenerator(nfpPair, config);
                generatedNfp.Add(dataTemp);
            }
            for (int i = 0; i < generatedNfp.Count; i++)
            {
                ParallelData Nfp = generatedNfp[i];
                //TODO remove gson & generate a new key algorithm
                String tkey = serialize.Serialize(Nfp.getKey()); //gson.toJson(Nfp.getKey());
                if (!nfpCache.ContainsKey(tkey))
                {
                    nfpCache.Add(tkey, Nfp.value);
                }
                else
                {
                }
            }

            PlacementWorker worker         = new PlacementWorker(binPolygon, config, nfpCache);
            List <NestPath> placeListSlice = new List <NestPath>();



            for (int i = 0; i < placelist.Count; i++)
            {
                placeListSlice.Add(new NestPath(placelist[i]));
            }
            List <List <NestPath> > data = new List <List <NestPath> >();

            data.Add(placeListSlice);
            List <Result> placements = new List <Result>();

            for (int i = 0; i < data.Count; i++)
            {
                Result result = worker.placePaths(data[i]);
                placements.Add(result);
            }
            if (placements.Count == 0)
            {
                return(null);
            }
            individual.fitness = placements[0].fitness;
            Result bestResult = placements[0];

            for (int i = 1; i < placements.Count; i++)
            {
                if (placements[i].fitness < bestResult.fitness)
                {
                    bestResult = placements[i];
                }
            }
            return(bestResult);
        }