static GCodeInfo GenerateGCodeForFile(string filename, Action <string, string> errorF, Func <bool> cancelF) { GCodeInfo info = new GCodeInfo(); DMesh3 mesh = StandardMeshReader.ReadMesh(filename); if (mesh == null || mesh.TriangleCount == 0) { throw new Exception("File " + filename + " is invalid or empty"); } bool ENABLE_SUPPORT_ZSHIFT = true; // configure settings MakerbotSettings settings = new MakerbotSettings(Makerbot.Models.Replicator2); //MonopriceSettings settings = new MonopriceSettings(Monoprice.Models.MP_Select_Mini_V2); //PrintrbotSettings settings = new PrintrbotSettings(Printrbot.Models.Plus); settings.ExtruderTempC = 200; settings.Shells = 2; settings.InteriorSolidRegionShells = 0; settings.SparseLinearInfillStepX = 10; settings.ClipSelfOverlaps = false; settings.GenerateSupport = true; settings.EnableSupportShell = true; PrintMeshAssembly meshes = new PrintMeshAssembly(); meshes.AddMesh(mesh); // slice meshes MeshPlanarSlicerPro slicer = new MeshPlanarSlicerPro() { LayerHeightMM = settings.LayerHeightMM, SliceFactoryF = PlanarSlicePro.FactoryF }; slicer.Add(meshes); slicer.CancelF = cancelF; PlanarSliceStack slices = slicer.Compute(); if (slicer.WasCancelled) { return(info); } info.SliceCount = slices.Count; info.SliceBounds = slices.Bounds; // run print generator SingleMaterialFFFPrintGenPro printGen = new SingleMaterialFFFPrintGenPro(meshes, slices, settings); printGen.ErrorF = errorF; printGen.CancelF = cancelF; if (ENABLE_SUPPORT_ZSHIFT) { printGen.LayerPostProcessor = new SupportConnectionPostProcessor() { ZOffsetMM = 0.2f } } ; printGen.AccumulatePathSet = true; printGen.Generate(); if (printGen.WasCancelled) { return(info); } GCodeFile genGCode = printGen.Result; info.PathBounds = printGen.AccumulatedPaths.Bounds; info.ExtrudeBounds = printGen.AccumulatedPaths.ExtrudeBounds; info.TotalLength = CurveUtils.ArcLength(printGen.AccumulatedPaths.AllPositionsItr()); info.GCodeLines = genGCode.LineCount; // write to in-memory string StandardGCodeWriter writer = new StandardGCodeWriter(); using (MemoryStream membuf = new MemoryStream()) { using (StreamWriter w = new StreamWriter(membuf)) { writer.WriteFile(genGCode, w); info.GCodeBytes = (int)membuf.Length; } } info.completed = true; return(info); } }
public override void Generate() { double tCurveLen = CurveUtils.ArcLength(Curve); SampledArcLengthParam pAxis = new SampledArcLengthParam(Axis, Axis.Length); double tAxisLen = pAxis.ArcLength; double tScale = tAxisLen / tCurveLen; int nRings = Curve.Length; int nRingSize = (NoSharedVertices) ? Slices + 1 : Slices; int nCapVertices = (NoSharedVertices) ? Slices + 1 : 1; if (Capped == false) { nCapVertices = 0; } vertices = new VectorArray3d(nRingSize * nRings + 2 * nCapVertices); uv = new VectorArray2f(vertices.Count); normals = new VectorArray3f(vertices.Count); int nSpanTris = (nRings - 1) * (2 * Slices); int nCapTris = (Capped) ? 2 * Slices : 0; triangles = new IndexArray3i(nSpanTris + nCapTris); float fDelta = (float)((Math.PI * 2.0) / Slices); double tCur = 0; CurveSample s = pAxis.Sample(tCur); Frame3f f0 = new Frame3f((Vector3F)s.position, (Vector3F)s.tangent, 1); Frame3f fCur = f0; // generate tube for (int ri = 0; ri < nRings; ++ri) { if (ri > 0) { tCur += (Curve[ri] - Curve[ri - 1]).Length; s = pAxis.Sample(tCur * tScale); fCur.Origin = (Vector3F)s.position; fCur.AlignAxis(1, (Vector3F)s.tangent); } Vector3D v_along = Curve[ri]; Vector3F v_frame = fCur.ToFrameP((Vector3F)v_along); float uv_along = (float)ri / (float)(nRings - 1); // generate vertices int nStartR = ri * nRingSize; for (int j = 0; j < nRingSize; ++j) { float angle = (float)j * fDelta; // [TODO] this is not efficient...use Matrix3f? Vector3F v_rot = Quaternionf.AxisAngleR(Vector3F.AxisY, angle) * v_frame; Vector3D v_new = fCur.FromFrameP(v_rot); int k = nStartR + j; vertices[k] = v_new; float uv_around = (float)j / (float)(nRingSize); uv[k] = new Vector2F(uv_along, uv_around); // [TODO] proper normal Vector3F n = (Vector3F)(v_new - fCur.Origin).Normalized; normals[k] = n; } } // generate triangles int ti = 0; for (int ri = 0; ri < nRings - 1; ++ri) { int r0 = ri * nRingSize; int r1 = r0 + nRingSize; for (int k = 0; k < nRingSize - 1; ++k) { triangles.Set(ti++, r0 + k, r0 + k + 1, r1 + k + 1, Clockwise); triangles.Set(ti++, r0 + k, r1 + k + 1, r1 + k, Clockwise); } if (NoSharedVertices == false) // close disc if we went all the way { triangles.Set(ti++, r1 - 1, r0, r1, Clockwise); triangles.Set(ti++, r1 - 1, r1, r1 + nRingSize - 1, Clockwise); } } if (Capped) { // find avg start loop size Vector3D vAvgStart = Vector3D.Zero, vAvgEnd = Vector3D.Zero; for (int k = 0; k < Slices; ++k) { vAvgStart += vertices[k]; vAvgEnd += vertices[(nRings - 1) * nRingSize + k]; } vAvgStart /= (double)Slices; vAvgEnd /= (double)Slices; Frame3f fStart = f0; fStart.Origin = (Vector3F)vAvgStart; Frame3f fEnd = fCur; fEnd.Origin = (Vector3F)vAvgEnd; // add endcap verts int nBottomC = nRings * nRingSize; vertices[nBottomC] = fStart.Origin; uv[nBottomC] = new Vector2F(0.5f, 0.5f); normals[nBottomC] = -fStart.Z; startCapCenterIndex = nBottomC; int nTopC = nBottomC + 1; vertices[nTopC] = fEnd.Origin; uv[nTopC] = new Vector2F(0.5f, 0.5f); normals[nTopC] = fEnd.Z; endCapCenterIndex = nTopC; if (NoSharedVertices) { // duplicate first loop and make a fan w/ bottom-center int nExistingB = 0; int nStartB = nTopC + 1; for (int k = 0; k < Slices; ++k) { vertices[nStartB + k] = vertices[nExistingB + k]; //uv[nStartB + k] = (Vector2f)Polygon.Vertices[k].Normalized; float angle = (float)k * fDelta; double cosa = Math.Cos(angle), sina = Math.Sin(angle); uv[nStartB + k] = new Vector2F(0.5f * (1.0f + cosa), 0.5f * (1 + sina)); normals[nStartB + k] = normals[nBottomC]; } append_disc(Slices, nBottomC, nStartB, true, Clockwise, ref ti); // duplicate second loop and make fan int nExistingT = nRingSize * (nRings - 1); int nStartT = nStartB + Slices; for (int k = 0; k < Slices; ++k) { vertices[nStartT + k] = vertices[nExistingT + k]; //uv[nStartT + k] = (Vector2f)Polygon.Vertices[k].Normalized; float angle = (float)k * fDelta; double cosa = Math.Cos(angle), sina = Math.Sin(angle); uv[nStartT + k] = new Vector2F(0.5f * (1.0f + cosa), 0.5f * (1 + sina)); normals[nStartT + k] = normals[nTopC]; } append_disc(Slices, nTopC, nStartT, true, !Clockwise, ref ti); } else { append_disc(Slices, nBottomC, 0, true, Clockwise, ref ti); append_disc(Slices, nTopC, nRingSize * (nRings - 1), true, !Clockwise, ref ti); } } }
static void Main(string[] args) { GCodeInfo info = new GCodeInfo(); string filename = args[0]; DMesh3 mesh = StandardMeshReader.ReadMesh(filename); AxisAlignedBox3d bounds = mesh.CachedBounds; MeshTransforms.Scale(mesh, MAX_DIM_MM / bounds.MaxDim); Vector3d basePt = mesh.CachedBounds.Point(0, 0, -1); MeshTransforms.Translate(mesh, -basePt); if (mesh.TriangleCount > MAX_TRI_COUNT) { Reducer r = new Reducer(mesh); r.ReduceToTriangleCount(MAX_TRI_COUNT); mesh = new DMesh3(mesh, true); } var start = DateTime.Now; bool ENABLE_SUPPORT_ZSHIFT = true; try { // configure settings MakerbotSettings settings = new MakerbotSettings(Makerbot.Models.Replicator2); //MonopriceSettings settings = new MonopriceSettings(Monoprice.Models.MP_Select_Mini_V2); //PrintrbotSettings settings = new PrintrbotSettings(Printrbot.Models.Plus); settings.ExtruderTempC = 200; settings.Shells = 2; settings.InteriorSolidRegionShells = 0; settings.SparseLinearInfillStepX = 10; settings.ClipSelfOverlaps = false; settings.GenerateSupport = true; settings.EnableSupportShell = true; PrintMeshAssembly meshes = new PrintMeshAssembly(); meshes.AddMesh(mesh); // slice meshes MeshPlanarSlicerPro slicer = new MeshPlanarSlicerPro() { LayerHeightMM = settings.LayerHeightMM, SliceFactoryF = PlanarSlicePro.FactoryF }; slicer.Add(meshes); PlanarSliceStack slices = slicer.Compute(); info.SliceCount = slices.Count; info.SliceBounds = slices.Bounds; // run print generator SingleMaterialFFFPrintGenPro printGen = new SingleMaterialFFFPrintGenPro(meshes, slices, settings); if (ENABLE_SUPPORT_ZSHIFT) { printGen.LayerPostProcessor = new SupportConnectionPostProcessor() { ZOffsetMM = 0.2f } } ; printGen.AccumulatePathSet = true; printGen.Generate(); GCodeFile genGCode = printGen.Result; info.PathBounds = printGen.AccumulatedPaths.Bounds; info.ExtrudeBounds = printGen.AccumulatedPaths.ExtrudeBounds; info.TotalLength = CurveUtils.ArcLength(printGen.AccumulatedPaths.AllPositionsItr()); info.GCodeLines = genGCode.LineCount; // write to in-memory string StandardGCodeWriter writer = new StandardGCodeWriter(); using (MemoryStream membuf = new MemoryStream()) { using (StreamWriter w = new StreamWriter(membuf)) { writer.WriteFile(genGCode, w); info.GCodeBytes = (int)membuf.Length; } } // try to force destructor error printGen = null; genGCode = null; GC.Collect(); } catch (Exception e) { System.Console.WriteLine("EXCEPTION:" + e.Message); return; } var end = DateTime.Now; int seconds = (int)(end - start).TotalSeconds; System.Console.WriteLine("{0},{1},{2},{3},{4},{5},{6},{7},", filename, mesh.TriangleCount, "OK", seconds, info.SliceCount, info.GCodeLines, info.GCodeBytes, (int)info.TotalLength); }
public DMesh3 CreateMesh(List <Vector3d> path, List <Polygon2d> polys, VectorArray3d seam) { // Ignore first and last path/polys for mesh generation. // We just need the extra path positions to calculate a // continuous tangent at the seams. List <Vector3d> pathXZ = new List <Vector3d>(); for (int i = 0; i < path.Count; i++) { pathXZ.Add(new Vector3d(path[i].x, 0, path[i].z)); } int nVerts = path.Count - 2; int nPolys = polys.Count - 2; // Same VertexCount for all Polygons. int nSlices = polys[0].VertexCount; int nPolySize = nSlices + 1; int nVecs = nVerts * nPolySize; vertices = new VectorArray3d(nVecs); normals = new VectorArray3f(nVecs); uv = new VectorArray2f(nVecs); int quad_strips = nVerts - 1; int nSpanTris = quad_strips * (2 * nSlices); triangles = new IndexArray3i(nSpanTris); Frame3f fCur = new Frame3f(frame); double pathLength = CurveUtils.ArcLength(path.GetRange(1, nVerts)); double accum_path_u = 0; for (int ri = 0; ri < nPolys; ++ri) { int si = ri + 1; // actual path/polys index for mesh Vector3d tangent = CurveUtils.GetTangent(pathXZ, si); fCur.Origin = (Vector3f)path[si]; fCur.AlignAxis(2, (Vector3f)tangent); int nStartR = ri * nPolySize; double accum_ring_v = 0; bool copy = ri == nPolys - 1; bool paste = ri == 0; for (int j = 0; j < nPolySize; ++j) { int k = nStartR + j; Vector2d pv = polys[si].Vertices[j % nSlices]; Vector2d pvNext = polys[si].Vertices[(j + 1) % nSlices]; Vector3d v = fCur.FromPlaneUV((Vector2f)pv, 2); vertices[k] = v; Vector3f n = (Vector3f)(v - fCur.Origin).Normalized; normals[k] = n; uv[k] = new Vector2f(accum_path_u, accum_ring_v); accum_ring_v += (pv.Distance(pvNext) / polys[si].ArcLength); if (copy) { Seam[j] = vertices[k]; } else if (paste) { vertices[k] = seam[j]; } } double d = path[si].Distance(path[si + 1]); accum_path_u += d / pathLength; } int nStop = nVerts - 1; int ti = 0; for (int ri = 0; ri < nStop; ++ri) { int r0 = ri * nPolySize; int r1 = r0 + nPolySize; for (int k = 0; k < nPolySize - 1; ++k) { triangles.Set(ti++, r0 + k, r0 + k + 1, r1 + k + 1, Clockwise); triangles.Set(ti++, r0 + k, r1 + k + 1, r1 + k, Clockwise); } } return(MakeDMesh()); }