public override IEnumerable <PenDrawingPath> generate() { CMDProcessPool pool = new CMDProcessPool(generatorConfig.MaxTSPThreads); TSPLibProblem[] tsps = new TSPLibProblem[pointSets.Count]; // // foreach list of points // make a tsp problem. // add it to the LKH job pool if no output file exists // for (int i = 0; i < pointSets.Count; ++i) { TSPLibProblem tsp = TSPLibProblem.FromPoints(pointSets[i].GetEnumerator(), BaseFileName + "." + i); if (!tsp.OutputFileExists()) { pool.Add(tsp.GetTSPCommand()); } tsps[i] = tsp; } pool.run(); // Output files should now exists for all tsp problems // create pen drawing paths from each of them for (int i = 0; i < pointSets.Count; ++i) { yield return(fromTSP(tsps[i], pointSets[i])); } }
public static TSPLibProblem FromPoints(IEnumerator <Vector2f> points, string IndicesInOutFileName, float multiplier = 100f) { TSPLibProblem tsp = new TSPLibProblem(IndicesInOutFileName); tsp.multiplier = multiplier; StringBuilder eucPoints = new StringBuilder(); while (points.MoveNext()) { Vector2f scaled = points.Current * tsp.multiplier; eucPoints.Append(string.Format("{0} {1} {2}\n", ++tsp.length, (int)scaled.x, (int)scaled.y)); } tsp.problemFileStr = string.Format(ProblemFormat, tsp.length, eucPoints.ToString()); tsp.WriteParamAndProbWithBaseName(tsp.IndicesInOutFileBaseName); return(tsp); }
PenDrawingPath fromTSP(TSPLibProblem tsp, List <Vector2f> points) { PenDrawingPath pdpath = new PenDrawingPath(); bool success = tsp.setIndicesFromOutputFile(); Debug.Log("TSP success? " + success); if (success) { for (int i = 0; i < points.Count; ++i) { pdpath.addDrawMove(points[tsp.indexAt(i)] * viewBoxToPaperScale); } } else { Debug.LogWarning("tsp encountered an error"); } Debug.Log("after add pts "); return(pdpath); }
void SolveTriTree(PenDrawingPath pdPath) { //CONSIDER: two passes // 1.) Dark very detailed // 2.) mid to light don't sweat the details as much //split tri tree leaves if not sufficiently populated if (generatorConfig.ShouldSplitUnderFilledTris) { triTree.root.SplitUnderPopulatedLeaves(generatorConfig.TriFilledThreshold, generatorConfig.MaxSplitToFillRecursionDepth); } triTree.root.CullDataWithMaxMean(bitMapPointGenerator.MaxGrayScale); List <IsoTriangle <PixelTriData> > subTrees; // split tree into max cities sub trees subTrees = triTree.root.NonEmptyChildrenWithMaxLeaves(generatorConfig.MaxTSPTriangleCities); //DEBUG var meshGO = MeshUtil.MakeGameObject(triTree.getMesh(), "CrosshatchTriTree"); var pool = new CMDProcessPool(generatorConfig.MaxTSPThreads); var subLeaves = new List <IsoTriangle <PixelTriData> > [subTrees.Count]; var tsps = new TSPLibProblem[subTrees.Count]; //DEBUG delete any previously generated files TSPLibProblem.GetDeleteAllCommand(BaseFileName + "*").ToCMDProcess().run(); for (int i = 0; i < subTrees.Count; ++i) { var tree = subTrees[i]; //get leaf centers var leaves = tree.GetLeaves(true); var centers = new List <Vector2f>(leaves.Count); for (int j = 0; j < leaves.Count; ++j) { centers.Add(leaves[j].center); } // solve each sub tree var tsp = TSPLibProblem.FromPoints(centers.GetEnumerator(), BaseFileName + ".tri." + i); if (!tsp.OutputFileExists()) { pool.Add(tsp.GetTSPCommand()); } subLeaves[i] = leaves; tsps[i] = tsp; } pool.run(); for (int i = 0; i < subTrees.Count; ++i) { // crosshatch sub trees var tsp = tsps[i]; if (!tsp.setIndicesFromOutputFile()) { Debug.LogWarning("no tsp indices"); continue; //TODO: handle more gracefully } var leaves = subLeaves[i]; TriCrosshatch <PixelTriData> tch = null, last = null; for (int j = 0; j < leaves.Count; ++j) { tch = new TriCrosshatch <PixelTriData>(this, leaves[tsp.indexAt(j)]); tch.last = last; tch.next = j == leaves.Count - 1 ? null : new TriCrosshatch <PixelTriData>(this, leaves[tsp.indexAt(j + 1)]); tch.AddDrawPoints(pdPath, viewBoxToPaperScale, (float)machineConfig.toolDiameterMM); last = tch; } } }