public void AddPolygonsTest() { PlanarSlice slice = new PlanarSlice(); Polygon2d p2d = new Polygon2d(new List <Vector2d>() { new Vector2d(1, 0), new Vector2d(0, 1), new Vector2d(1, 1) }); GeneralPolygon2d poly = new GeneralPolygon2d(p2d); Polygon2d p2d2 = new Polygon2d(new List <Vector2d>() { new Vector2d(-1, 0), new Vector2d(0, -1), new Vector2d(-1, -1) }); GeneralPolygon2d poly2 = new GeneralPolygon2d(p2d2); slice.AddPolygons(new List <GeneralPolygon2d>() { poly, poly2 }); Assert.AreEqual(slice.InputSolids[0], poly); Assert.AreEqual(slice.InputSolids[1], poly2); }
public void AddClippedPathTest() { PlanarSlice slice = new PlanarSlice(); PolyLine2d line = new PolyLine2d(new List <Vector2d>() { new Vector2d(1, 0), new Vector2d(-1, 0) }); slice.AddClippedPath(line); Assert.AreEqual(slice.ClippedPaths[0], line); }
public void ResolveEmbeddedPathWidthExceptionTest() { PlanarSlice slice = new PlanarSlice(); PolyLine2d line = new PolyLine2d(new List <Vector2d>() { new Vector2d(1, 0), new Vector2d(-1, 0) }); slice.AddEmbeddedPath(line); Assert.ThrowsException <Exception>(() => slice.Resolve()); }
public void AddSupportPolygonTest() { PlanarSlice slice = new PlanarSlice(); Polygon2d p2d = new Polygon2d(new List <Vector2d>() { new Vector2d(1, 0), new Vector2d(0, 1), new Vector2d(1, 1) }); GeneralPolygon2d poly = new GeneralPolygon2d(p2d); slice.AddSupportPolygon(poly); Assert.IsTrue(slice.SupportSolids[0] == poly); }
public void AddCropRegionTest() { PlanarSlice slice = new PlanarSlice(); Polygon2d p2d = new Polygon2d(new List <Vector2d>() { new Vector2d(1, 0), new Vector2d(0, 1), new Vector2d(1, 1) }); GeneralPolygon2d poly = new GeneralPolygon2d(p2d); slice.AddCropRegion(poly); Assert.IsTrue(slice.InputCropRegions[0] == poly); }
private void DrawLayerSlice(PlanarSliceStack stack, SKCanvas canvas, SKPaint paint) { SKColor pathColor = SkiaUtil.Color(255, 0, 0, 255); paint.Color = pathColor; paint.Style = SKPaintStyle.Stroke; paint.StrokeWidth = 2.0f; if (currentLayer >= stack.Slices.Count) { return; } PlanarSlice slice = stack.Slices[currentLayer]; foreach (GeneralPolygon2d poly in slice.Solids) { SKPath path = MakePaths(poly, SceneToSkiaF); canvas.DrawPath(path, paint); } }
public void ComputeOnBackgroundThread() { Deviation = null; DebugUtil.Log(SO.GetToolpathStats()); ToolpathSet paths = SO.GetToolpaths(); PlanarSliceStack slices = SO.GetSlices(); var settings = SO.GetSettings(); // AAHHH double bed_width = settings.Machine.BedSizeXMM; double bed_height = settings.Machine.BedSizeYMM; Vector3d origin = new Vector3d(-bed_width / 2, -bed_height / 2, 0); if (settings is gs.info.MakerbotSettings) { origin = Vector3d.Zero; } List <DeviationPt> points = new List <DeviationPt>(); SpinLock pointsLock = new SpinLock(); Action <DeviationPt> appendPointF = (pt) => { bool entered = false; pointsLock.Enter(ref entered); points.Add(pt); pointsLock.Exit(); }; double tolerance = settings.Machine.NozzleDiamMM * 0.5 + DeviationToleranceMM; gParallel.ForEach(Interval1i.Range(slices.Count), (slicei) => { PlanarSlice slice = slices[slicei]; //Interval1d zrange = (slicei < slices.Count - 1) ? // new Interval1d(slice.Z, slices[slicei + 1].Z - 0.5*settings.LayerHeightMM) : // new Interval1d(slice.Z, slice.Z + 0.5*settings.LayerHeightMM); double dz = 0.5 * settings.LayerHeightMM; Interval1d zrange = new Interval1d(slice.Z - dz, slice.Z + dz); double cellSize = 2.0f; ToolpathsLayerGrid grid = new ToolpathsLayerGrid(); grid.Build(paths, zrange, cellSize); foreach (GeneralPolygon2d poly in slice.Solids) { measure_poly(poly.Outer, slice.Z, grid, tolerance, appendPointF); foreach (var hole in poly.Holes) { measure_poly(poly.Outer, slice.Z, grid, tolerance, appendPointF); } } }); int N = points.Count; for (int k = 0; k < N; ++k) { DeviationPt pt = points[k]; Vector3d v = origin + pt.pos; v = MeshTransforms.ConvertZUpToYUp(v); pt.pos = MeshTransforms.FlipLeftRightCoordSystems(v); points[k] = pt; } Deviation = new DeviationData(); Deviation.DeviationPoints = points; OnGeometryUpdateRequired?.Invoke(this); }
public void DistanceSquaredExceptionTest() { PlanarSlice slice = new PlanarSlice(); Assert.ThrowsException <Exception>(() => slice.DistanceSquared(new Vector2d(0, 0))); }
public void ResolveTest() { PlanarSlice slice = new PlanarSlice(); Polygon2d p2d = new Polygon2d(new List <Vector2d>() { new Vector2d(1, 0), new Vector2d(0, 1), new Vector2d(1, 1) }); GeneralPolygon2d poly = new GeneralPolygon2d(p2d); Polygon2d p2d2 = new Polygon2d(new List <Vector2d>() { new Vector2d(-1, 0), new Vector2d(0, -1), new Vector2d(-1, -1) }); GeneralPolygon2d poly2 = new GeneralPolygon2d(p2d2); slice.AddPolygons(new List <GeneralPolygon2d>() { poly, poly2 }); Assert.AreEqual(slice.InputSolids[0], poly); Assert.AreEqual(slice.InputSolids[1], poly2); PolyLine2d line = new PolyLine2d(new List <Vector2d>() { new Vector2d(1, 0), new Vector2d(-1, 0) }); slice.AddEmbeddedPath(line); slice.EmbeddedPathWidth = 1; Polygon2d supportp2d = new Polygon2d(new List <Vector2d>() { new Vector2d(1, 0), new Vector2d(0, 1), new Vector2d(1, 1) }); GeneralPolygon2d supportpoly = new GeneralPolygon2d(supportp2d); Polygon2d supportp2d2 = new Polygon2d(new List <Vector2d>() { new Vector2d(-1, 0), new Vector2d(0, -1), new Vector2d(-1, -1) }); GeneralPolygon2d supportpoly2 = new GeneralPolygon2d(supportp2d2); slice.AddSupportPolygons(new List <GeneralPolygon2d>() { supportpoly, supportpoly2 }); Polygon2d cavp2d = new Polygon2d(new List <Vector2d>() { new Vector2d(1, 0), new Vector2d(0, 1), new Vector2d(1, 1) }); GeneralPolygon2d cavpoly = new GeneralPolygon2d(cavp2d); Polygon2d cavp2d2 = new Polygon2d(new List <Vector2d>() { new Vector2d(-1, 0), new Vector2d(0, -1), new Vector2d(-1, -1) }); GeneralPolygon2d cavpoly2 = new GeneralPolygon2d(cavp2d2); slice.AddCavityPolygons(new List <GeneralPolygon2d>() { cavpoly, cavpoly2 }); Polygon2d cropp2d = new Polygon2d(new List <Vector2d>() { new Vector2d(1, 0), new Vector2d(0, 1), new Vector2d(1, 1) }); GeneralPolygon2d croppoly = new GeneralPolygon2d(cropp2d); Polygon2d cropp2d2 = new Polygon2d(new List <Vector2d>() { new Vector2d(-1, 0), new Vector2d(0, -1), new Vector2d(-1, -1) }); GeneralPolygon2d croppoly2 = new GeneralPolygon2d(cropp2d2); slice.AddCropRegions(new List <GeneralPolygon2d>() { croppoly, croppoly2 }); slice.Resolve(); slice.BuildSpatialCaches(); double dist = slice.DistanceSquared(new Vector2d(5, 5)); Assert.AreEqual(41, dist); }
static GCodeFile generate_cnc_test(MeshPlanarMillSlicer.Result sliceSets, RepRapSettings settings, out ToolpathSet AccumulatedPaths) { int PLUNGE_SPEED = 800; AccumulatedPaths = new ToolpathSet(); GCodeFileAccumulator file_accumulator = new GCodeFileAccumulator(); GCodeBuilder builder = new GCodeBuilder(file_accumulator); BaseThreeAxisMillingCompiler Compiler = new BaseThreeAxisMillingCompiler(builder, settings, GenericMillingAssembler.Factory); Compiler.Begin(); /* * Clearing pass */ PlanarSliceStack clearingSlices = sliceSets.Clearing; int N = clearingSlices.Count; // assuming origin is at top of stock so we actaully are going down in Z layers for (int k = 0; k < N; ++k) { clearingSlices[k].Z = -(sliceSets.TopZ - clearingSlices[k].Z); } for (int layeri = 0; layeri < N; layeri++) { PlanarSlice slice = clearingSlices[layeri]; Compiler.AppendComment(string.Format("clearing layer {0} - {1}mm", layeri, slice.Z)); ToolpathSetBuilder layer_builder = new ToolpathSetBuilder() { MoveType = ToolpathTypes.Cut }; layer_builder.Initialize(Compiler.ToolPosition); // To do a layer-change, we need to plunge down at the first scheduled cutting position. // However we will not know that until we schedule the first set of paths. // So, we configure SequentialScheduler2d to call this function when it knows this information, // and then we can travel to the new XY position before we plunge to new Z Action <List <FillCurveSet2d>, SequentialScheduler2d> DoZChangeF = (curves, scheduler) => { Vector2d startPosXY = (curves[0].Loops.Count > 0) ? curves[0].Loops[0].Start : curves[0].Curves[0].Start; Vector3d startPosXYZ = new Vector3d(startPosXY.x, startPosXY.y, slice.Z); // TODO: we should retract at faster speed here? maybe use custom function that does this better? layer_builder.AppendTravel(startPosXYZ, PLUNGE_SPEED); scheduler.OnAppendCurveSetsF = null; }; SequentialScheduler2d layerScheduler = new SequentialScheduler2d(layer_builder, settings) { ExtrudeOnShortTravels = true, ShortTravelDistance = settings.Machine.NozzleDiamMM * 1.5 }; layerScheduler.OnAppendCurveSetsF = DoZChangeF; GroupScheduler2d groupScheduler = new GroupScheduler2d(layerScheduler, Compiler.ToolPosition.xy); foreach (GeneralPolygon2d shape in slice.Solids) { ShellsFillPolygon shells_gen = new ShellsFillPolygon(shape) { PathSpacing = settings.ShellsFillPathSpacingMM(), ToolWidth = settings.Machine.NozzleDiamMM, Layers = 10, OuterShellLast = false, DiscardTinyPerimterLengthMM = 1, DiscardTinyPolygonAreaMM2 = 1 }; shells_gen.Compute(); groupScheduler.BeginGroup(); groupScheduler.AppendCurveSets(shells_gen.Shells); groupScheduler.EndGroup(); } Compiler.AppendPaths(layer_builder.Paths, settings); AccumulatedPaths.Append(layer_builder.Paths); } /* * Horizontal finish pass */ PlanarSliceStack horzSlices = sliceSets.HorizontalFinish; int NH = horzSlices.Count; // assuming origin is at top of stock so we actaully are going down in Z layers for (int k = 0; k < NH; ++k) { horzSlices[k].Z = -(sliceSets.TopZ - horzSlices[k].Z); } for (int layeri = 0; layeri < NH; layeri++) { PlanarSlice slice = horzSlices[layeri]; Compiler.AppendComment(string.Format("horz finish layer {0} - {1}mm", layeri, slice.Z)); ToolpathSetBuilder layer_builder = new ToolpathSetBuilder() { MoveType = ToolpathTypes.Cut }; layer_builder.Initialize(Compiler.ToolPosition); Action <List <FillCurveSet2d>, SequentialScheduler2d> DoZChangeF = (curves, scheduler) => { Vector2d startPosXY = (curves[0].Loops.Count > 0) ? curves[0].Loops[0].Start : curves[0].Curves[0].Start; Vector3d startPosXYZ = new Vector3d(startPosXY.x, startPosXY.y, slice.Z); // TODO: we should retract at faster speed here? maybe use custom function that does this better? layer_builder.AppendTravel(startPosXYZ, PLUNGE_SPEED); scheduler.OnAppendCurveSetsF = null; }; SequentialScheduler2d layerScheduler = new SequentialScheduler2d(layer_builder, settings) { ExtrudeOnShortTravels = true, ShortTravelDistance = settings.Machine.NozzleDiamMM * 1.5 }; layerScheduler.OnAppendCurveSetsF = DoZChangeF; GroupScheduler2d groupScheduler = new GroupScheduler2d(layerScheduler, Compiler.ToolPosition.xy); foreach (GeneralPolygon2d shape in slice.Solids) { ShellsFillPolygon shells_gen = new ShellsFillPolygon(shape) { //InsetFromInputPolygonX = 0.0, PathSpacing = settings.ShellsFillPathSpacingMM(), ToolWidth = settings.Machine.NozzleDiamMM, Layers = 10, OuterShellLast = false, PreserveInputInsetTopology = false, DiscardTinyPerimterLengthMM = 1, DiscardTinyPolygonAreaMM2 = 1 }; shells_gen.Compute(); groupScheduler.BeginGroup(); groupScheduler.AppendCurveSets(shells_gen.Shells); groupScheduler.EndGroup(); } Compiler.AppendPaths(layer_builder.Paths, settings); AccumulatedPaths.Append(layer_builder.Paths); } // return to home position ToolpathSetBuilder finishBuilder = new ToolpathSetBuilder() { MoveType = ToolpathTypes.Cut }; finishBuilder.Initialize(Compiler.ToolPosition); finishBuilder.AppendTravel(Vector3d.Zero, PLUNGE_SPEED); Compiler.AppendPaths(finishBuilder.Paths, settings); Compiler.End(); return(file_accumulator.File); }
void OnExpose(object sender, ExposeEventArgs args) { DrawingArea area = (DrawingArea)sender; Cairo.Context cr = Gdk.CairoHelper.Create(area.GdkWindow); int width = area.Allocation.Width; int height = area.Allocation.Height; AxisAlignedBox3d bounds3 = Stack.Bounds; AxisAlignedBox2d bounds = (bounds3 == AxisAlignedBox3d.Empty) ? new AxisAlignedBox2d(0, 0, 500, 500) : new AxisAlignedBox2d(bounds3.Min.x, bounds3.Min.y, bounds3.Max.x, bounds3.Max.y); double sx = (double)width / bounds.Width; double sy = (double)height / bounds.Height; float scale = (float)Math.Min(sx, sy); // we apply this translate after scaling to pixel coords Vector2f pixC = Zoom * scale * (Vector2f)bounds.Center; Vector2f translate = new Vector2f(width / 2, height / 2) - pixC; using (var bitmap = new SKBitmap(width, height, SkiaUtil.ColorType(), SKAlphaType.Premul)) { IntPtr len; using (var skSurface = SKSurface.Create(bitmap.Info.Width, bitmap.Info.Height, SkiaUtil.ColorType(), SKAlphaType.Premul, bitmap.GetPixels(out len), bitmap.Info.RowBytes)) { var canvas = skSurface.Canvas; canvas.Clear(SkiaUtil.Color(240, 240, 240, 255)); Func <Vector2d, Vector2f> xformF = (pOrig) => { Vector2f pNew = (Vector2f)pOrig; pNew -= (Vector2f)bounds.Center; pNew = Zoom * scale * pNew; pNew += (Vector2f)pixC; pNew += translate + Zoom * Translate; pNew.y = canvas.LocalClipBounds.Height - pNew.y; return(pNew); }; Func <Vector2d, SKPoint> mapToSkiaF = (pOrig) => { Vector2f p = xformF(pOrig); return(new SKPoint(p.x, p.y)); }; using (var paint = new SKPaint()) { SKBitmap sliceImg = get_slice_image(currentLayer); float w = sliceImg.Width / CurrentDPIMM, h = sliceImg.Height / CurrentDPIMM; w *= Zoom * scale; h *= Zoom * scale; SKPoint sliceCenter = mapToSkiaF(Vector2d.Zero); SKRect drawRect = new SKRect( sliceCenter.X - w / 2, sliceCenter.Y - h / 2, sliceCenter.X + w / 2, sliceCenter.Y + h / 2); canvas.DrawBitmap(sliceImg, drawRect, paint); paint.IsAntialias = true; paint.Style = SKPaintStyle.Stroke; PlanarSlice slice = Stack.Slices[currentLayer]; paint.Color = SkiaUtil.Color(255, 0, 0, 255);; paint.StrokeWidth = 2; foreach (GeneralPolygon2d poly in slice.Solids) { SKPath path = SkiaUtil.ToSKPath(poly, mapToSkiaF); canvas.DrawPath(path, paint); } } Cairo.Surface surface = new Cairo.ImageSurface( bitmap.GetPixels(out len), Cairo.Format.Argb32, bitmap.Width, bitmap.Height, bitmap.Width * 4); surface.MarkDirty(); cr.SetSourceSurface(surface, 0, 0); cr.Paint(); } } //return true; }