private void slicefunc() { try { //first take care of scaling up the output bitmap paramters size, so we can re-sample later double scaler = 1.5; // specify the scale factor m_saved.CopyFrom(m_sf.m_config); // save the original if (m_sf.m_config.antialiasing == true) { scaler = m_sf.m_config.aaval; // scale them up. m_sf.m_config.dpmmX *= scaler; m_sf.m_config.dpmmY *= scaler; m_sf.m_config.xres = (int)(m_sf.m_config.xres * scaler); m_sf.m_config.yres = (int)(m_sf.m_config.yres * scaler); } else { scaler = 1.0; // no scaling } //determine the number of slices //UVDLPApp.Instance().Scene.FindMinMax(); MinMax mm = UVDLPApp.Instance().Engine3D.CalcSceneExtents(); //int numslices = (int)((mm.m_max - mm.m_min) / m_sf.m_config.ZThick); int numslices = (int)((mm.m_max) / m_sf.m_config.ZThick); //int numslices = (int)((UVDLPApp.Instance().Scene.m_max.z) / m_sf.m_config.ZThick); // I should start slicing at Wz 0, not Oz 0 float curz = 0; // start at Wz0 // an alternative here is to slice the scene from wZ 0, therefore, all object geometry beneath the ground plane won't be slice; //double curz = (double)0.0;// start at the ground int c = 0; string scenename = ""; // a little housework here... foreach (Object3d obj in UVDLPApp.Instance().Engine3D.m_objects) { obj.CalcMinMaxes(); if (c == 0) { //get the first objects' name scenename = obj.m_fullname; m_sf.modelname = obj.m_fullname; } c++; } m_sf.NumSlices = numslices; SliceStarted(scenename, numslices); DebugLogger.Instance().LogRecord("Slicing started"); if (m_sf.m_config.export == false) { // if we're not actually exporting slices right now, then // raise the completed event and exit SliceCompleted(scenename, 0, numslices); m_sf.m_config.CopyFrom(m_saved); isslicing = false; return; // exit slicing, nothing more to do... } for (c = 0; c < numslices; c++) { Bitmap bmp = new Bitmap(m_sf.m_config.xres, m_sf.m_config.yres); // create a new bitmap on a per-slice basis //clear the image for rendering Graphics graph = Graphics.FromImage(bmp); graph.Clear(UVDLPApp.Instance().m_appconfig.m_backgroundcolor); //convert all to 2d lines Bitmap savebm = null; // check for cancelation if (m_cancel) { isslicing = false; m_cancel = false; //restore the original sizes m_sf.m_config.CopyFrom(m_saved); RaiseSliceEvent(eSliceEvent.eSliceCancelled, c, numslices); return; } foreach (Object3d obj in UVDLPApp.Instance().Engine3D.m_objects) { savebm = bmp; // need to set this here in case it's not rendered if (curz >= obj.m_min.z && curz <= obj.m_max.z) // only slice from the bottom to the top of the objects { //obj.ClearCached(); List <Polygon> lstply = GetZPolys(obj, curz); //get a list of polygons at this slice z height that potentially intersect List <PolyLine3d> lstintersections = GetZIntersections(lstply, curz); //iterate through all the polygons and generate x/y line segments at this 3d z level Slice sl = new Slice(); //create a new slice sl.m_segments = lstintersections; // Set the list of intersections // m_sf.m_slices.Add(sl);// add the slice to slicefile // now render the slice into the scaled, pre-allocated bitmap sl.RenderSlice(m_sf.m_config, ref bmp); savebm = bmp; } } if (m_sf.m_config.antialiasing == true) // we're using anti-aliasing here, so resize the image { savebm = ResizeImage(bmp, new Size(m_saved.xres, m_saved.yres)); } if (m_sf.m_config.m_flipX == true) { savebm = ReflectX(savebm); } if (m_sf.m_config.m_flipY == true) { savebm = ReflectY(savebm); } curz += (float)m_sf.m_config.ZThick;// move the slice for the next layer //raise an event to say we've finished a slice LayerSliced(scenename, c, numslices, savebm); } // restore the original m_sf.m_config.CopyFrom(m_saved); SliceCompleted(scenename, c, numslices); DebugLogger.Instance().LogRecord("Slicing Completed"); isslicing = false; } catch (Exception ex) { string s = ex.StackTrace; DebugLogger.Instance().LogRecord(ex.Message); //RaiseSliceEvent(eSliceEvent.eSliceCancelled,0,0); m_cancel = true; } }
private void slicefunc() { try { //first take care of scaling up the output bitmap paramters size, so we can re-sample later double scaler = 1.5; // specify the scale factor m_saved.CopyFrom(m_sf.m_config); // save the original if (m_sf.m_config.antialiasing == true) { scaler = m_sf.m_config.aaval; // scale them up. m_sf.m_config.dpmmX *= scaler; m_sf.m_config.dpmmY *= scaler; m_sf.m_config.xres = (int)(m_sf.m_config.xres * scaler); m_sf.m_config.yres = (int)(m_sf.m_config.yres * scaler); } else { scaler = 1.0; // no scaling } //determine the number of slices //UVDLPApp.Instance().Scene.FindMinMax(); MinMax mm = UVDLPApp.Instance().Engine3D.CalcSceneExtents(); int numslices = (int)((mm.m_max - mm.m_min) / m_sf.m_config.ZThick); //int numslices = (int)((UVDLPApp.Instance().Scene.m_max.z) / m_sf.m_config.ZThick); // I should start slicing at Wz 0, not Oz 0 float curz = 0; // start at Wz0 // an alternative here is to slice the scene from wZ 0, therefore, all object geometry beneath the ground plane won't be slice; //double curz = (double)0.0;// start at the ground int c = 0; string scenename = ""; // a little housework here... foreach (Object3d obj in UVDLPApp.Instance().Engine3D.m_objects) { obj.CalcMinMaxes(); if (c == 0) { //get the first objects' name scenename = obj.m_fullname; m_sf.modelname = obj.m_fullname; } c++; } m_sf.NumSlices = numslices; SliceStarted(scenename, numslices); DebugLogger.Instance().LogRecord("Slicing started"); if (m_sf.m_config.export == false) { // if we're not actually exporting slices right now, then // raise the completed event and exit SliceCompleted(scenename, 0, numslices); m_sf.m_config.CopyFrom(m_saved); isslicing = false; return; // exit slicing, nothing more to do... } for (c = 0; c < numslices; c++) { Bitmap bmp = new Bitmap(m_sf.m_config.xres,m_sf.m_config.yres); // create a new bitmap on a per-slice basis //clear the image for rendering Graphics graph = Graphics.FromImage(bmp); graph.Clear(UVDLPApp.Instance().m_appconfig.m_backgroundcolor); //convert all to 2d lines Bitmap savebm = null; // check for cancelation if (m_cancel) { isslicing = false; m_cancel = false; //restore the original sizes m_sf.m_config.CopyFrom(m_saved); RaiseSliceEvent(eSliceEvent.eSliceCancelled, c, numslices); return; } foreach (Object3d obj in UVDLPApp.Instance().Engine3D.m_objects) { savebm = bmp; // need to set this here in case it's not rendered if (curz >=obj.m_min.z && curz <= obj.m_max.z) // only slice from the bottom to the top of the objects { //obj.ClearCached(); ArrayList lstply = GetZPolys(obj, curz);//get a list of polygons at this slice z height that potentially intersect ArrayList lstintersections = GetZIntersections(lstply, curz);//iterate through all the polygons and generate x/y line segments at this 3d z level Slice sl = new Slice();//create a new slice sl.m_segments = lstintersections;// Set the list of intersections // m_sf.m_slices.Add(sl);// add the slice to slicefile // now render the slice into the scaled, pre-allocated bitmap sl.RenderSlice(m_sf.m_config, ref bmp); savebm = bmp; } } if (m_sf.m_config.antialiasing == true) // we're using anti-aliasing here, so resize the image { savebm = ResizeImage(bmp, new Size(m_saved.xres,m_saved.yres)); } if (m_sf.m_config.m_flipX == true) { savebm = ReflectX(savebm); } if (m_sf.m_config.m_flipY == true) { savebm = ReflectY(savebm); } curz += (float)m_sf.m_config.ZThick;// move the slice for the next layer //raise an event to say we've finished a slice LayerSliced(scenename, c,numslices,savebm); } // restore the original m_sf.m_config.CopyFrom(m_saved); SliceCompleted(scenename, c, numslices); DebugLogger.Instance().LogRecord("Slicing Completed"); isslicing = false; } catch (Exception ex) { string s = ex.StackTrace; DebugLogger.Instance().LogRecord(ex.Message); //RaiseSliceEvent(eSliceEvent.eSliceCancelled,0,0); m_cancel = true; } }
/// <summary> /// This function will immediately return a bitmap slice at the specified Z-Level /// </summary> /// <param name="zlev"></param> /// <returns></returns> public Bitmap SliceImmediate(float curz) { try { //first take care of scaling up the output bitmap paramters size, so we can re-sample later double scaler = 1.5; // specify the scale factor m_saved.CopyFrom(m_sf.m_config); // save the orginal if (m_sf.m_config.antialiasing == true) { scaler = m_sf.m_config.aaval; m_sf.m_config.dpmmX *= scaler; m_sf.m_config.dpmmY *= scaler; m_sf.m_config.xres = (int)(scaler * m_sf.m_config.xres); m_sf.m_config.yres = (int)(scaler * m_sf.m_config.yres); } SliceBuildConfig sbf = new SliceBuildConfig(m_sf.m_config); // save it Bitmap bmp = new Bitmap(m_sf.m_config.xres, m_sf.m_config.yres); // create a new bitmap on a per-slice basis Graphics graph = Graphics.FromImage(bmp); graph.Clear(UVDLPApp.Instance().m_appconfig.m_backgroundcolor); //clear the image for rendering //convert all to 2d lines Bitmap savebm = null; // check for cancelation foreach (Object3d obj in UVDLPApp.Instance().Engine3D.m_objects) { savebm = bmp; // need to set this here in case it's not rendered if (curz >= obj.m_min.z && curz <= obj.m_max.z) // only slice from the bottom to the top of the objects { List <Polygon> lstply = GetZPolys(obj, curz); //get a list of polygons at this slice z height that potentially intersect List <PolyLine3d> lstintersections = GetZIntersections(lstply, curz); //iterate through all the polygons and generate x/y line segments at this 3d z level Slice sl = new Slice(); //create a new slice sl.m_segments = lstintersections; // Set the list of intersections sl.RenderSlice(m_sf.m_config, ref bmp); savebm = bmp; } } if (m_sf.m_config.antialiasing == true) // we're using anti-aliasing here, so resize the image { savebm = ResizeImage(bmp, new Size(m_saved.xres, m_saved.yres)); } if (m_sf.m_config.m_flipX == true) { savebm = ReflectX(savebm); } if (m_sf.m_config.m_flipY == true) { savebm = ReflectY(savebm); } //restore the original size m_sf.m_config.CopyFrom(m_saved); return(savebm); } catch (Exception ex) { string s = ex.StackTrace; DebugLogger.Instance().LogRecord(ex.Message); return(null); } }
/// <summary> /// This function will immediately return a bitmap slice at the specified Z-Level /// </summary> /// <param name="zlev"></param> /// <returns></returns> public Bitmap SliceImmediate(float curz) { try { //first take care of scaling up the output bitmap paramters size, so we can re-sample later double scaler = 1.5; // specify the scale factor m_saved.CopyFrom(m_sf.m_config);// save the orginal if (m_sf.m_config.antialiasing == true) { scaler = m_sf.m_config.aaval; m_sf.m_config.dpmmX *= scaler; m_sf.m_config.dpmmY *= scaler; m_sf.m_config.xres = (int)(scaler * m_sf.m_config.xres); m_sf.m_config.yres = (int)(scaler * m_sf.m_config.yres); } SliceBuildConfig sbf = new SliceBuildConfig(m_sf.m_config); // save it Bitmap bmp = new Bitmap(m_sf.m_config.xres, m_sf.m_config.yres); // create a new bitmap on a per-slice basis Graphics graph = Graphics.FromImage(bmp); graph.Clear(UVDLPApp.Instance().m_appconfig.m_backgroundcolor);//clear the image for rendering //convert all to 2d lines Bitmap savebm = null; // check for cancelation foreach (Object3d obj in UVDLPApp.Instance().Engine3D.m_objects) { savebm = bmp; // need to set this here in case it's not rendered if (curz >= obj.m_min.z && curz <= obj.m_max.z) // only slice from the bottom to the top of the objects { ArrayList lstply = GetZPolys(obj, curz);//get a list of polygons at this slice z height that potentially intersect ArrayList lstintersections = GetZIntersections(lstply, curz);//iterate through all the polygons and generate x/y line segments at this 3d z level Slice sl = new Slice();//create a new slice sl.m_segments = lstintersections;// Set the list of intersections sl.RenderSlice(m_sf.m_config, ref bmp); savebm = bmp; } } if (m_sf.m_config.antialiasing == true) // we're using anti-aliasing here, so resize the image { savebm = ResizeImage(bmp,new Size(m_saved.xres,m_saved.yres)); } if (m_sf.m_config.m_flipX == true) { savebm = ReflectX(savebm); } if (m_sf.m_config.m_flipY == true) { savebm = ReflectY(savebm); } //restore the original size m_sf.m_config.CopyFrom(m_saved); return savebm; } catch (Exception ex) { string s = ex.StackTrace; DebugLogger.Instance().LogRecord(ex.Message); return null; } }
/// <summary> /// This is the adaptive support generation, it should automatically /// detect overhangs, /// The way that it does this is by generating a closed polyline loop for each layer /// and checking the 2d projection of the current layer with the previous layer /// </summary> public void GenerateAdaptive() { //iterate through all the layers starting from z=0 // check every polyline in the current layer to make sure it is encased or overlaps polylines in the previous layer // generate a list of unsupported polylines // 'check' to see if the polyline can be dropped straight down // this has to do slicing of the scene SliceBuildConfig config = UVDLPApp.Instance().m_buildparms; List <UnsupportedRegions> lstunsup = new List <UnsupportedRegions>(); List <Object3d> lstsupports = new List <Object3d>(); // final list of supports int numslices = UVDLPApp.Instance().m_slicer.GetNumberOfSlices(config); float zlev = 0.0f; Slice curslice = null; Slice prevslice = null; int hxres = config.xres / 2; int hyres = config.yres / 2; for (int c = 0; c < numslices; c++) { if (m_cancel) { RaiseSupportEvent(UV_DLP_3D_Printer.SupportEvent.eCancel, "Support Generation Cancelled", null); return; } RaiseSupportEvent(UV_DLP_3D_Printer.SupportEvent.eProgress, "" + c + "/" + numslices, null); Slice sl = UVDLPApp.Instance().m_slicer.GetSliceImmediate(zlev); sl.Optimize();// find loops zlev += (float)config.ZThick; prevslice = curslice; curslice = sl; Bitmap bm = new Bitmap(config.xres, config.yres); if (prevslice != null && curslice != null) { //render current slice curslice.RenderSlice(config, ref bm); //now render the previous slice overtop the current slice in another color Color savecol = UVDLPApp.Instance().m_appconfig.m_foregroundcolor; UVDLPApp.Instance().m_appconfig.m_foregroundcolor = Color.HotPink; //render previous slice over top prevslice.RenderSlice(config, ref bm); UVDLPApp.Instance().m_appconfig.m_foregroundcolor = savecol; // restore the color // create a lock bitmap for faster pixel access LockBitmap lbm = new LockBitmap(bm); lbm.LockBits(); // now, iterate through all optimized polylines in current slice // this approach isn't going to work, we need to iterate through all polyline //segments in a slice at once, each individual segment needs to know 1 thing // 1) the optimized segment it came from foreach (PolyLine3d pln in curslice.m_opsegs) { // each polyline region is checked separately bool plysupported = false; //split this optimized polyline back into 2-point segments for easier use List <PolyLine3d> segments = pln.Split(); List <Line2d> lines2d = Get2dLines(config, segments); // find the x/y min/max MinMax_XY mm = Slice.CalcMinMax_XY(lines2d); // iterate from the ymin to the ymax for (int y = mm.ymin; y < mm.ymax; y++) // this needs to be in scaled value { // get a line of lines that intersect this 2d line List <Line2d> intersecting = Slice.GetIntersecting2dYLines(y, lines2d); // get the list of point intersections List <Point2d> points = Slice.GetIntersectingPoints(y, intersecting); // sort the points in increasing x order points.Sort(); if (points.Count % 2 == 0) // is even { for (int cnt = 0; cnt < points.Count; cnt += 2) // increment by 2 { Point2d p1 = (Point2d)points[cnt]; Point2d p2 = (Point2d)points[cnt + 1]; Point pnt1 = new Point(); // create some points for drawing Point pnt2 = new Point(); pnt1.X = (int)(p1.x + config.XOffset + hxres); pnt1.Y = (int)(p1.y + config.YOffset + hyres); pnt2.X = (int)(p2.x + config.XOffset + hxres); pnt2.Y = (int)(p2.y + config.YOffset + hyres); //iterate from pnt1.X to pnt2.x and check colors for (int xc = pnt1.X; xc < pnt2.X; xc++) { Color checkcol = lbm.GetPixel(xc, pnt1.Y); // need to check the locked BM here for the right color // if the pixel color is the hot pink, then this region has some support // we're going to need to beef this up and probably divide this all into regions on a grid if (checkcol.R == Color.HotPink.R && checkcol.G == Color.HotPink.G && checkcol.B == Color.HotPink.B) { plysupported = true; } } } } else // flag error { DebugLogger.Instance().LogRecord("Row y=" + y + " odd # of points = " + points.Count + " - Model may have holes"); } }// for y = startminY to endY if (plysupported == false) { //generate a support, or mark where a support should be... lstunsup.Add(new UnsupportedRegions(pln)); } else { plysupported = true; } } // for each optimized polyline lbm.UnlockBits(); // unlock the bitmap } // prev and current slice are not null } // iterating through all slices RaiseSupportEvent(UV_DLP_3D_Printer.SupportEvent.eCompleted, "Support Generation Completed", lstsupports); m_generating = false; }
/// <summary> /// This function will immediately return a bitmap slice at the specified Z-Level /// If lstPoly is not null, a list of vector polylines representing the slice is returned /// </summary> /// <param name="zlev"></param> /// <param name="lstPoly"></param> /// <returns></returns> //public Bitmap SliceImmediate(float curz, List<PolyLine3d> lstPoly = null) public Bitmap SliceImmediate(float curz, List <PolyLine3d> allIntersections, bool outline = true, bool bottomLayers = false) { outline = true; try { //first take care of scaling up the output bitmap paramters size, so we can re-sample later double scaler = 1.5; // specify the scale factor m_saved.CopyFrom(m_sf.m_config); // save the orginal if (m_sf.m_config.antialiasing == true) { scaler = m_sf.m_config.aaval; m_sf.m_config.dpmmX *= scaler; m_sf.m_config.dpmmY *= scaler; m_sf.m_config.xres = (int)(scaler * m_sf.m_config.xres); m_sf.m_config.yres = (int)(scaler * m_sf.m_config.yres); } SliceBuildConfig sbf = new SliceBuildConfig(m_sf.m_config); // save it Bitmap bmp = new Bitmap(m_sf.m_config.xres, m_sf.m_config.yres); // create a new bitmap on a per-slice basis using (Graphics graph = Graphics.FromImage(bmp)) { graph.Clear(UVDLPApp.Instance().m_appconfig.m_backgroundcolor); graph.DrawRectangle(new Pen(new SolidBrush(UVDLPApp.Instance().m_appconfig.m_foregroundcolor), (float)m_sf.m_config.m_wall_thickness), new Rectangle(0, 0, m_sf.m_config.xres, m_sf.m_config.yres)); //graph.DrawString("omid", new Font(new FontFamily("Tahoma"), 10 ,FontStyle.Bold), new SolidBrush(Color.Red), new PointF(2, 299)); //clear the image for rendering if (bottomLayers) { graph.Clear(UVDLPApp.Instance().m_appconfig.m_backgroundcolor); } } //convert all to 2d lines Bitmap savebm = null; // check for cancelation foreach (Object3d obj in UVDLPApp.Instance().Engine3D.m_objects) { savebm = bmp; // need to set this here in case it's not rendered if (curz >= obj.m_min.z && curz <= obj.m_max.z) // only slice from the bottom to the top of the objects { List <Polygon> lstply = GetZPolys(obj, curz); //get a list of polygons at this slice z height that potentially intersect List <PolyLine3d> lstintersections = GetZIntersections(lstply, curz); //iterate through all the polygons and generate x/y line segments at this 3d z level Slice sl = new Slice(); //create a new slice sl.m_segments = lstintersections; // Set the list of intersections sl.RenderSlice(m_sf.m_config, ref bmp, outline); if (allIntersections != null) { allIntersections.AddRange(lstintersections); } savebm = bmp; } } if (m_sf.m_config.antialiasing == true) // we're using anti-aliasing here, so resize the image { savebm = ResizeImage(bmp, new Size(m_saved.xres, m_saved.yres)); } if (m_sf.m_config.m_flipX == true) { savebm = ReflectX(savebm); } if (m_sf.m_config.m_flipY == true) { savebm = ReflectY(savebm); } //restore the original size m_sf.m_config.CopyFrom(m_saved); return(savebm); } catch (Exception ex) { string s = ex.StackTrace; DebugLogger.Instance().LogError(ex); return(null); } }
/// <summary> /// This is the adaptive support generation, it should automatically /// detect overhangs and generate supports acordingly /// </summary> public void GenerateAdaptive2() { // iterate through all the layers starting from z=0 // slice all layers // split each layer into non overlapping polygons // check each polygon to see if it is completely overhangs in the air, or partially // supported by previous layers. // for complete overhangs always create supports // for partialy supported polygons, generate supports only if there is no other // support in the vicinity try { SliceBuildConfig config = UVDLPApp.Instance().m_buildparms; config.UpdateFrom(UVDLPApp.Instance().m_printerinfo); // make sure we've got the correct display size and PixPerMM values if (UVDLPApp.Instance().m_slicer.SliceFile == null) { SliceFile sf = new SliceFile(config); sf.m_mode = SliceFile.SFMode.eImmediate; UVDLPApp.Instance().m_slicer.SliceFile = sf; // wasn't set } //create new list for new supports List <Object3d> lstsupports = new List <Object3d>(); // final list of supports List <SupportLocation> supLocs = new List <SupportLocation>(); // temporary list of support locations. int numslices = UVDLPApp.Instance().m_slicer.GetNumberOfSlices(config); float zlev = (float)(config.ZThick + 0.5); int hxres = config.xres / 2; int hyres = config.yres / 2; int npix = config.xres * config.yres; int[] lbm = new int[npix]; // current slice int[] lbmz = new int[npix]; // z buffer bool[] lbms = new bool[npix]; // support map int p; for (p = 0; p < npix; p++) { lbmz[p] = 0; lbms[p] = false; } Bitmap bm = new Bitmap(config.xres, config.yres, System.Drawing.Imaging.PixelFormat.Format32bppArgb); // working bitmap Color savecol = UVDLPApp.Instance().m_appconfig.m_foregroundcolor; m_supportgap = (int)(m_sc.mingap * config.dpmmX); m_asp.lbm = lbm; m_asp.lbms = lbms; m_asp.lbmz = lbmz; m_asp.searchmap = new int[npix]; m_asp.xres = config.xres; m_asp.yres = config.yres; m_asp.mingap = m_supportgap; for (int c = 0; c < numslices; c++) { //bool layerneedssupport = false; if (m_cancel) { RaiseSupportEvent(UV_DLP_3D_Printer.SupportEvent.eCancel, "Support Generation Cancelled", null); return; } RaiseSupportEvent(UV_DLP_3D_Printer.SupportEvent.eProgress, "" + c + "/" + numslices, null); Slice sl = UVDLPApp.Instance().m_slicer.GetSliceImmediate(zlev); zlev += (float)config.ZThick; if ((sl == null) || (sl.m_segments == null) || (sl.m_segments.Count == 0)) { continue; } sl.Optimize();// find loops using (Graphics gfx = Graphics.FromImage(bm)) gfx.Clear(Color.Transparent); //render current slice UVDLPApp.Instance().m_appconfig.m_foregroundcolor = Color.FromArgb((0xFF << 24) | c); sl.RenderSlice(config, ref bm); BitmapData data = bm.LockBits(new Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); Marshal.Copy(data.Scan0, lbm, 0, lbm.Length); for (p = 0; p < npix; p++) { lbm[p] &= 0xFFFFFF; } bm.UnlockBits(data); if (c > 0) { if (m_sc.eSupType == SupportConfig.eAUTOSUPPORTTYPE.eADAPTIVE) { ProcessSlice(lbm, lbmz, lbms, config.xres, config.yres, supLocs); } else { ProcessSlice2(supLocs); } } // add slice to zbuffer bitmap for (p = 0; p < npix; p++) { if (lbm[p] != 0) { lbmz[p] = lbm[p]; } } } UVDLPApp.Instance().m_appconfig.m_foregroundcolor = savecol; int scnt = 0; foreach (SupportLocation spl in supLocs) { float px = (float)(spl.x - hxres) / (float)config.dpmmX; float py = (float)(spl.y - hyres) / (float)config.dpmmY; float pz = (float)(spl.ztop) * (float)config.ZThick; pz += .650f; // wtf? AddNewSupport(px, py, pz, scnt++, GetSupportParrent(px, py, pz), lstsupports); } RaiseSupportEvent(UV_DLP_3D_Printer.SupportEvent.eCompleted, "Support Generation Completed", lstsupports); m_generating = false; } catch (Exception ex) { DebugLogger.Instance().LogError(ex); } }
/// <summary> /// NOT CURRENTLY USED /// This is the adaptive support generation, it should automatically /// detect overhangs, /// The way that it does this is by generating a closed polyline loop for each layer /// and checking the 2d projection of the current layer with the previous layer /// </summary> public void GenerateAdaptive() { //iterate through all the layers starting from z=0 // check every polyline in the current layer to make sure it is encased or overlaps polylines in the previous layer // generate a list of unsupported polylines // 'check' to see if the polyline can be dropped straight down // this has to do slicing of the scene try { SliceBuildConfig config = UVDLPApp.Instance().m_buildparms; config.UpdateFrom(UVDLPApp.Instance().m_printerinfo); // make sure we've got the correct display size and PixPerMM values if (UVDLPApp.Instance().m_slicer.SliceFile == null) { SliceFile sf = new SliceFile(config); sf.m_mode = SliceFile.SFMode.eImmediate; UVDLPApp.Instance().m_slicer.SliceFile = sf; // wasn't set } //create new list for each layer to hold unsupported regions List <UnsupportedRegions> lstunsup = new List <UnsupportedRegions>(); List <Object3d> lstsupports = new List <Object3d>(); // final list of supports int numslices = UVDLPApp.Instance().m_slicer.GetNumberOfSlices(config); float zlev = (float)(config.ZThick / 2.0); Slice curslice = null; Slice prevslice = null; int hxres = config.xres / 2; int hyres = config.yres / 2; for (int c = 0; c < numslices; c++) { //bool layerneedssupport = false; if (m_cancel) { RaiseSupportEvent(UV_DLP_3D_Printer.SupportEvent.eCancel, "Support Generation Cancelled", null); return; } RaiseSupportEvent(UV_DLP_3D_Printer.SupportEvent.eProgress, "" + c + "/" + numslices, null); Slice sl = UVDLPApp.Instance().m_slicer.GetSliceImmediate(zlev); zlev += (float)config.ZThick; if (sl == null) { continue; } if (sl.m_segments == null) { continue; } if (sl.m_segments.Count == 0) { continue; } sl.Optimize();// find loops //sl.DetermineInteriorExterior(config); // mark the interior/exterior loops prevslice = curslice; curslice = sl; Bitmap bm = new Bitmap(config.xres, config.yres); using (Graphics gfx = Graphics.FromImage(bm)) using (SolidBrush brush = new SolidBrush(Color.Black)) { gfx.FillRectangle(brush, 0, 0, bm.Width, bm.Height); } if (prevslice != null && curslice != null) { //render current slice curslice.RenderSlice(config, ref bm); //now render the previous slice overtop the current slice in another color Color savecol = UVDLPApp.Instance().m_appconfig.m_foregroundcolor; UVDLPApp.Instance().m_appconfig.m_foregroundcolor = Color.HotPink; //render previous slice over top prevslice.RenderSlice(config, ref bm); UVDLPApp.Instance().m_appconfig.m_foregroundcolor = savecol; // restore the color // create a lock bitmap for faster pixel access LockBitmap lbm = new LockBitmap(bm); lbm.LockBits(); // now, iterate through all optimized polylines in current slice // this approach isn't going to work, we need to iterate through all polyline //segments in a slice at once, each individual segment needs to know 1 thing // 1) the optimized segment it came from //iterate through all optimized polygon segments Dictionary <PolyLine3d, bool> supportmap = new Dictionary <PolyLine3d, bool>(); foreach (PolyLine3d pln in curslice.m_opsegs) { bool plysupported = false; List <PolyLine3d> allsegments = new List <PolyLine3d>(); List <PolyLine3d> segments = pln.Split(); // split them, retaining the parent allsegments.AddRange(segments); //add all optimized polyline segments into the supported map supportmap.Add(pln, true); //split this optimized polyline back into 2-point segments for easier use List <Line2d> lines2d = Get2dLines(config, allsegments); if (lines2d.Count == 0) { continue; } // find the x/y min/max MinMax_XY mm = Slice.CalcMinMax_XY(lines2d); // iterate from the ymin to the ymax for (int y = mm.ymin; y < mm.ymax; y++) // this needs to be in scaled value { // get a line of lines that intersect this 2d line List <Line2d> intersecting = Slice.GetIntersecting2dYLines(y, lines2d); // get the list of point intersections List <Point2d> points = Slice.GetIntersectingPoints(y, intersecting); // sort the points in increasing x order points.Sort(); if (points.Count % 2 == 0) // is even { for (int cnt = 0; cnt < points.Count; cnt += 2) // increment by 2 { Point2d p1 = (Point2d)points[cnt]; Point2d p2 = (Point2d)points[cnt + 1]; Point pnt1 = new Point(); // create some points for drawing Point pnt2 = new Point(); pnt1.X = (int)(p1.x + config.XOffset + hxres); pnt1.Y = (int)(p1.y + config.YOffset + hyres); pnt2.X = (int)(p2.x + config.XOffset + hxres); pnt2.Y = (int)(p2.y + config.YOffset + hyres); //iterate from pnt1.X to pnt2.x and check colors for (int xc = pnt1.X; xc < pnt2.X; xc++) { if (xc >= lbm.Width || xc <= 0) { continue; } if (pnt1.Y >= lbm.Height || pnt1.Y <= 0) { continue; } try { Color checkcol = lbm.GetPixel(xc, pnt1.Y); // need to check the locked BM here for the right color // if the pixel color is the hot pink, then this region has some support // we're going to need to beef this up and probably divide this all into regions on a grid if (checkcol.R == Color.HotPink.R && checkcol.G == Color.HotPink.G && checkcol.B == Color.HotPink.B) { plysupported = true; } } catch (Exception ex) { DebugLogger.Instance().LogError(ex); } } } } else // flag error { DebugLogger.Instance().LogRecord("Row y=" + y + " odd # of points = " + points.Count + " - Model may have holes"); } }// for y = startminY to endY if (plysupported == false) { // layerneedssupport = true; supportmap[pln] = false; lstunsup.Add(new UnsupportedRegions(pln)); } } // for each optimized polyline lbm.UnlockBits(); // unlock the bitmap } // prev and current slice are not null //if (layerneedssupport) // SaveBM(bm, c); // uncomment this to see the layers that need support } // iterating through all slices // iterate through all unsupported regions // calculate the center // add a support from that region going down to the ground (or closest intersected) int scnt = 0; foreach (UnsupportedRegions region in lstunsup) { Support s = new Support(); Point3d center = region.Center(); // taking the center of the region is a naive approach float lz = center.z; lz += .65f; // why is this offset needed? AddNewSupport(center.x, center.y, center.z, scnt++, null, lstsupports); } RaiseSupportEvent(UV_DLP_3D_Printer.SupportEvent.eCompleted, "Support Generation Completed", lstsupports); m_generating = false; } catch (Exception ex) { DebugLogger.Instance().LogError(ex); } }