private List<List<Point3D>> GenerateSlicePaths(Model3DGroup obj, double vs, double hs) { var bounds = new Rect3D(); MeshGeometry3D geom = null; Dispatch(() => { bounds = obj.Bounds; geom = obj.Children.OfType<GeometryModel3D>().First().Geometry as MeshGeometry3D; }); var res = new List<List<Point3D>>(); List<List<Point3D>> xpaths = null; for (var i = bounds.Location.Z + bounds.Size.Z; i >= bounds.Location.Z; i -= vs) { IList<Tuple<int, int>> des = null; List<Point3D> points = null; Dispatch(() => { // ReSharper disable once AccessToModifiedClosure var modl = geom.Slice(new Point3D(0, 0, i - vs), new Vector3D(0, 0, vs), EPSILON); points = modl.Positions.ToList(); des = modl.FindBottomContours(EPSILON); }); if (des.Count == 0) continue; var paths = new List<List<int>>(); var dict = des.Union(des.Select(x => Tuple.Create(x.Item2, x.Item1))).GroupBy(x => x.Item1).ToDictionary(x => x.Key, x => x.Select(y => y.Item2).ToList()); while (dict.Count > 0) { var fp = dict.Where(x => x.Value.Count() == 1).Union(dict) .Select(x => Tuple.Create(x.Key, x.Value.First())).FirstOrDefault(); var fpath = new List<int>(); paths.Add(fpath); var ind = fp.Item1; while (dict.ContainsKey(ind)) { fpath.Add(ind); var d = dict; var tmp = ind; ind = d[ind].First(); if (d.ContainsKey(tmp)) { d[tmp].Remove(ind); if (d[tmp].Count == 0) d.Remove(tmp); } if (d.ContainsKey(ind)) { d[ind].Remove(tmp); if (d[ind].Count == 0) d.Remove(ind); } fpath.Add(ind); } } var paths1 = paths.FixMergeIndexPaths(points, EPSILON).Select(x => x.Select(y => points[y]).ToList()).ToList(); var hstep = 4; xpaths = xpaths.ClipPaths(paths1, ClipType.Union, i, EPSILON).RemoveSmallPolygons(1, hstep*3, hstep).FixPointPaths(); var co = new ClipperOffset(); co.AddPaths(xpaths.ChangePointUnits(), JoinType.Round, EndType.ClosedPolygon); var xpathsres = new List<List<Point3D>>(); var j = 1; do { int nonFixed; var xpathsn = co.Execute(hs*j).ChangePointUnits(i - bounds.Location.Z).FixBounds(bounds, hs*3, out nonFixed); if (nonFixed == 0) break; j++; xpathsres = xpathsres.Union(xpathsn).ToList(); } while (true); xpathsres.JoinNearPoints(EPSILON); res.AddRange(xpathsres); } return res; }
private async Task FlatFileOpen() { var path = fileDialogService.OpenFileDialog("models", null, PointImporterExporterFactory.OpenFileDialogFilter, PointImporterExporterFactory.OpenFileDialogDefault); if (!string.IsNullOrEmpty(path)) { var cpx = PointImporterExporterFactory.Import(path); if (cpx != null) { var ctx = cpx.Bounds; if (ctx != null) cpx.MoveBy(new Point(-(ctx.Item1.X + ctx.Item2.X) / 2, -(ctx.Item1.Y + ctx.Item2.Y) / 2)); var cp = cpx.FlattenHierarchy(); var co = new ClipperOffset(); co.AddPaths(cp.Select(x => x.Select(y => y).ToList()).ToList(), JoinType.Round, EndType.ClosedPolygon); CurrentPaths = co.Execute(DRILL_STEP, EPSILON).Select((x, i) => x.Select(y => new Point3D(y.X, y.Y, 0)).ToList()).ToList(); } } }