private String m_preliftcode; // inserted before each slice #endregion Fields #region Constructors /* Copy constructor */ public SliceBuildConfig(SliceBuildConfig source) { dpmmX = source.dpmmX; // dots per mm x dpmmY = source.dpmmY; // dots per mm y xres = source.xres; yres = source.yres; // the resolution of the output image ZThick = source.ZThick; // thickness of the z layer - slicing height layertime_ms = source.layertime_ms; // time to project image per layer in milliseconds firstlayertime_ms = source.firstlayertime_ms; blanktime_ms = source.blanktime_ms; plat_temp = source.plat_temp; // desired platform temperature in celsius exportgcode = source.exportgcode; // export the gcode file when slicing exportsvg = source.exportsvg; // export the svg slices when building exportimages = source.exportimages; // export image slices when building m_headercode = source.m_headercode; // inserted at beginning of file m_footercode = source.m_footercode; // inserted at end of file m_preliftcode = source.m_preliftcode; // inserted between each slice m_postliftcode = source.m_postliftcode; // inserted between each slice liftdistance = source.liftdistance; direction = source.direction; numfirstlayers = source.numfirstlayers; XOffset = source.XOffset; YOffset = source.YOffset; raise_time_ms = source.raise_time_ms; }
public int GetNumberOfSlices(SliceBuildConfig sp, Object3d obj) { try { obj.FindMinMax(); int numslices = (int)((obj.m_max.z - obj.m_min.z) / sp.ZThick); return numslices; } catch (Exception) { return 0; } }
/// <summary> /// This will get the number of slices in the scene from the specified slice config /// This uses the Scene object from the app, we slice with individual objects though /// </summary> /// <param name="sp"></param> /// <returns></returns> public int GetNumberOfSlices(SliceBuildConfig sp) { try { //UVDLPApp.Instance().CalcScene(); MinMax mm = UVDLPApp.Instance().Engine3D.CalcSceneExtents(); // get the scene min/max //int numslices = (int)((UVDLPApp.Instance().Scene.m_max.z - UVDLPApp.Instance().Scene.m_min.z) / sp.ZThick); int numslices = (int)((mm.m_max - mm.m_min) / sp.ZThick); return numslices; } catch (Exception) { m_cancel = true; return 0; } }
//alright, it looks like I'm going to have to code up a 2d scanline fill algorithm // I suppose the first step is to convert all the 3d-ish polyline points in this slice into // 2d polylines, then use those to implement the fill /// <summary> /// This new slicing function renders into a pre-allocated bitmap /// </summary> /// <param name="sp"></param> /// <param name="bmp"></param> public void RenderSlice(SliceBuildConfig sp, ref Bitmap bmp) { try { Graphics graph = Graphics.FromImage(bmp); Point pnt1 = new Point(); // create some points for drawing Point pnt2 = new Point(); Pen pen = new Pen(UVDLPApp.Instance().m_appconfig.m_foregroundcolor, 1); //convert all to 2d lines int hxres = sp.xres / 2; int hyres = sp.yres / 2; List <Line2d> lines2d = Get2dLines(sp); if (lines2d.Count == 0) { return; } Render2dlines(graph, lines2d, sp); // find the x/y min/max MinMax_XY mm = 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 = GetIntersecting2dYLines(y, lines2d); // get the list of point intersections List <Point2d> points = GetIntersectingPoints(y, intersecting); // sort the points in increasing x order //SortXIncreasing(points); points.Sort(); // draw the X-Spans (should be even number) // For a given pair of intersectin points // (Xi, Y), (Xj, Y) // −> Fill ceiling(Xi) to floor(Xj) 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]; pnt1.X = (int)(p1.x + sp.XOffset + hxres); pnt1.Y = (int)(p1.y + sp.YOffset + hyres); pnt2.X = (int)(p2.x + sp.XOffset + hxres); pnt2.Y = (int)(p2.y + sp.YOffset + hyres); //graph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; graph.DrawLine(pen, pnt1.X, pnt1.Y, pnt2.X, pnt2.Y); } } else // flag error { DebugLogger.Instance().LogRecord("Row y=" + y + " odd # of points = " + points.Count + " - Model may have holes"); } } } catch (Exception ex) { DebugLogger.Instance().LogError(ex.Message); } }
// this function takes the object, the slicing parameters, // and the output directory. it generates the object slices // and saves them in the directory public SliceFile Slice(SliceBuildConfig sp, Object3d obj, String outdir) { m_obj = obj; m_cancel = false; // create new slice file m_sf = new SliceFile(sp); m_slicethread = new Thread(new ThreadStart(slicefunc)); m_slicethread.Start(); isslicing = true; return m_sf; }
// this function converts all the 3d polyines to 2d lines so we can process everything private ArrayList Get2dLines(SliceBuildConfig sp) { ArrayList lst = new ArrayList(); foreach (PolyLine3d ply in m_segments) { Line2d ln = new Line2d(); //get the 3d points of the line Point3d p3d1 = (Point3d)ply.m_points[0]; Point3d p3d2 = (Point3d)ply.m_points[1]; //convert them to 2d (probably should add an offset to center them) ln.p1.x = (int)(p3d1.x * sp.dpmmX);// +hxres; ln.p1.y = (int)(p3d1.y * sp.dpmmY);// +hyres; ln.p2.x = (int)(p3d2.x * sp.dpmmX);// +hxres; ln.p2.y = (int)(p3d2.y * sp.dpmmY);// +hyres; lst.Add(ln); } return lst; // return the list }
/// <summary> /// This get slice immediate is currently for previewing only /// </summary> /// <param name="curz"></param> /// <returns></returns> public Slice GetSliceImmediate(float curz) { try { SliceBuildConfig sbf = new SliceBuildConfig(m_sf.m_config); // save it Slice sl = new Slice();//create a new slice sl.m_segments = new List<PolyLine3d>(); foreach (Object3d obj in UVDLPApp.Instance().Engine3D.m_objects) { 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 sl.m_segments.AddRange(lstintersections);// Set the list of intersections } } return sl; } catch (Exception ex) { string s = ex.StackTrace; DebugLogger.Instance().LogRecord(ex.Message); return null; } }
//, Object3d obj) // this function takes the object, the slicing parameters, // and the output directory. it generates the object slices // and saves them in the directory public SliceFile Slice(SliceBuildConfig sp) { //m_obj = obj; m_cancel = false; // create new slice file m_sf = new SliceFile(sp); if (sp.export == false) { m_sf.m_mode = SliceFile.SFMode.eImmediate; } m_slicethread = new Thread(new ThreadStart(slicefunc)); m_slicethread.Start(); isslicing = true; return m_sf; }
private UVDLPApp() { m_appconfig = new AppConfig(); m_printerinfo = new MachineConfig(); m_buildparms = new SliceBuildConfig(); m_deviceinterface = new DeviceInterface(); m_buildmgr = new BuildManager(); m_slicer = new Slicer(); m_slicer.Slice_Event += new Slicer.SliceEvent(SliceEv); m_flexslice = new FlexSlice(); m_gcode = null; }
public bool LoadBuildSliceProfile(string filename) { m_buildparms = new SliceBuildConfig(); bool ret = m_buildparms.Load(filename); if (ret) { m_appconfig.m_cursliceprofilename = filename; m_appconfig.Save(m_appconfigname);// this name doesn't change } return ret; }
/// <summary> /// this function converts all the 3d polyines to 2d lines so we can process everything /// This is the equivanlant of a 3d->2d projection function /// </summary> /// <param name="sp"></param> /// <returns></returns> private List<Line2d> Get2dLines(SliceBuildConfig sp, List<PolyLine3d> segments) { List<Line2d> lst = new List<Line2d>(); foreach (PolyLine3d ply in segments) { for (int c = 0; c < ply.m_points.Count - 1; c++ ) { Line2d ln = new Line2d(); ln.SetParent(ply); //get the 3d points of the line Point3d p3d1 = (Point3d)ply.m_points[c]; Point3d p3d2 = (Point3d)ply.m_points[c + 1]; //convert them to 2d (probably should add an offset to center them) ln.p1.x = (int)(p3d1.x * sp.dpmmX); ln.p1.y = (int)(p3d1.y * sp.dpmmY); ln.p2.x = (int)(p3d2.x * sp.dpmmX); ln.p2.y = (int)(p3d2.y * sp.dpmmY); lst.Add(ln); } } return lst; // return the list }
private void RenderOutlines(Graphics g, SliceBuildConfig sp) { //optimize the polylines to join short segements into longer segments in correct winding order Optimize(); Pen pen_inset = null; Pen pen_outset = null; //create the appropriate pen pen_inset = new Pen(UVDLPApp.Instance().m_appconfig.m_foregroundcolor, (float)sp.m_outlinewidth_inset); pen_inset.Alignment = PenAlignment.Inset; pen_outset = new Pen(UVDLPApp.Instance().m_appconfig.m_foregroundcolor, (float)sp.m_outlinewidth_outset); pen_outset.Alignment = PenAlignment.Outset; //outset lines by definition will not meet at the corners, try to add some rounding to account for this. pen_outset.EndCap = LineCap.Round; pen_outset.StartCap = LineCap.Round; //get the half resolution for offsetting int hxres = sp.xres / 2; int hyres = sp.yres / 2; // iterate through all the polylines in m_opsegs //m_opsegs now contains 0 or more 3d polylines foreach(PolyLine3d pln in m_opsegs) { Point[] pntlst = new Point[pln.m_points.Count]; //iterate through all the 3d points in this polyline segment for (int c = 0; c < pln.m_points.Count ; c++) { // we must project these to 2d similar to Get2dLines //3d to 2d conversion Point3d p3d1 = (Point3d)pln.m_points[c]; Point pnt2d = new Point(); pnt2d.X = (int)(p3d1.x * sp.dpmmX); pnt2d.Y = (int)(p3d1.y * sp.dpmmY); // 2d offseting pnt2d.X = (int)(pnt2d.X) + sp.XOffset + hxres; pnt2d.Y = (int)(pnt2d.Y) + sp.YOffset + hyres; pntlst[c] = pnt2d; // set the item in the array } //now render it g.DrawPolygon(pen_inset, pntlst); if (sp.m_outlinewidth_outset > 0) { g.DrawPolygon(pen_outset, pntlst); } } // dispose of the pen pen_inset.Dispose(); pen_outset.Dispose(); }
/* * Copy constructor */ public SliceBuildConfig(SliceBuildConfig source) { CopyFrom(source); }
/// <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 = false) { 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, 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); } }
public void CopyFrom(SliceBuildConfig source) { dpmmX = source.dpmmX; // dots per mm x dpmmY = source.dpmmY; // dots per mm y xres = source.xres; yres = source.yres; // the resolution of the output image ZThick = source.ZThick; // thickness of the z layer - slicing height layertime_ms = source.layertime_ms; // time to project image per layer in milliseconds firstlayertime_ms = source.firstlayertime_ms; blanktime_ms = source.blanktime_ms; plat_temp = source.plat_temp; // desired platform temperature in celsius // exportgcode = source.exportgcode; // export the gcode file when slicing exportsvg = source.exportsvg; // export the svg slices when building export = source.export; // export image slices when building exportpng = source.exportpng; m_headercode = source.m_headercode; // inserted at beginning of file m_footercode = source.m_footercode; // inserted at end of file m_preslicecode = source.m_preslicecode; // inserted before each slice m_liftcode = source.m_liftcode; // its the main lift code m_layercode = source.m_layercode; // its the main lift code liftdistance = source.liftdistance; direction = source.direction; numfirstlayers = source.numfirstlayers; XOffset = source.XOffset; YOffset = source.YOffset; slidetiltval = source.slidetiltval; antialiasing = source.antialiasing; usemainliftgcode = source.usemainliftgcode; liftfeedrate = source.liftfeedrate; bottomliftfeedrate = source.bottomliftfeedrate; liftretractrate = source.liftretractrate; aaval = source.aaval;// //m_generateautosupports = source.m_generateautosupports; m_exportopt = source.m_exportopt; m_flipX = source.m_flipX; m_flipY = source.m_flipY; m_notes = source.m_notes; m_resinprice = source.m_resinprice; selectedInk = source.selectedInk; selectedpowder = source.selectedpowder; selectedfluid = source.selectedfluid; m_createoutlines = source.m_createoutlines; m_outlinewidth_inset = source.m_outlinewidth_inset; m_outlinewidth_outset = source.m_outlinewidth_outset; if (source.inks != null) { inks = new Dictionary <string, InkConfig>(); foreach (KeyValuePair <string, InkConfig> entry in source.inks) { inks[entry.Key] = entry.Value; } } if (source.fluids != null) { fluids = new Dictionary <string, FluidConfig>(); foreach (KeyValuePair <string, FluidConfig> entry in source.fluids) { fluids[entry.Key] = entry.Value; } } if (source.powders != null) { powders = new Dictionary <string, PowderConfig>(); foreach (KeyValuePair <string, PowderConfig> entry in source.powders) { powders[entry.Key] = entry.Value; } } minExposure = source.minExposure; exposureStep = source.exposureStep; exportpreview = source.exportpreview; userParams = source.userParams; m_feed_thickness = source.m_feed_thickness; m_speed_spareading = source.m_speed_spareading; m_speed_printing = source.m_speed_printing; m_bottom_layers = source.m_bottom_layers; m_roller_speed = source.m_roller_speed; m_wall_thickness = source.m_wall_thickness; }
private UVDLPApp() { m_supportmode = eSupportEditMode.eNone; SceneFileName = ""; m_callbackhandler = new CallbackHandler(); m_appconfig = new AppConfig(); m_printerinfo = new MachineConfig(); m_buildparms = new SliceBuildConfig(); m_deviceinterface = new DeviceInterface(); m_buildmgr = new BuildManager(); m_slicer = new Slicer(); m_slicer.m_slicemethod = Slicer.eSliceMethod.eNormalCount;// configure the slicer to user the new normal count - Thanks Shai!!! m_slicer.Slice_Event += new Slicer.SliceEvent(SliceEv); //m_dispmgr = DisplayManager.Instance(); // initialize the singleton for early event app binding //m_flexslice = new FlexSlice(); m_gcode = new GCodeFile(""); // create a blank gcode to start with m_supportconfig = new SupportConfig(); m_supportgenerator = new SupportGenerator(); m_supportgenerator.SupportEvent+= new SupportGeneratorEvent(SupEvent); CSG.Instance().CSGEvent += new CSG.CSGEventDel(CSGEvent); m_proj_cmd_lst = new prjcmdlst(); m_plugins = new List<PluginEntry>(); // list of user plug-ins m_pluginstates = PluginStates.Instance(); // initialize the plugin state singleton m_undoer = new Undoer(); m_2d_graphics = new C2DGraphics(); m_gui_config = new GuiConfigManager(); m_AuxBuildCmds = AuxBuildCmds.Instance(); // make sure the singleton doesn't go away... m_sequencemanager = SequenceManager.Instance(); m_exporter = new frmExport(); m_exporter.RegisterExporter(new B9JExporter()); }
public frmSliceOptions(ref SliceBuildConfig config) { m_config = config; InitializeComponent(); }
/// <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 = 0.0f; 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; 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> /// Make and show a new calibration image /// modificado por boris /// </summary> /// <param name="xres"></param> /// <param name="yres"></param> /// <param name="sc"></param> public void ShowCalibration(int xres, int yres, SliceBuildConfig sc) { // if (m_calibimage == null) // blank image is null, create it { //xres = 1024; //yres = 768; m_calibimage = new Bitmap(xres,yres); m_calibimage.Tag = BuildManager.SLICE_CALIBRATION; // fill it with black using (Graphics gfx = Graphics.FromImage(m_calibimage)) using (SolidBrush brush = new SolidBrush(Color.DarkSlateBlue)) { gfx.FillRectangle(brush, 0, 0, xres, yres); int xpos = 0, ypos = 0; Pen pen = new Pen(new SolidBrush(Color.White)); var radio = 25; var radX = (int)(radio * sc.dpmmX); var rady = (int)(radio * sc.dpmmY); gfx.DrawEllipse(pen, new Rectangle((xres / 2) - radX/2, (yres / 2)- rady/2, radX, rady)); gfx.DrawString("Prueba\r\nCALIBRACION", new Font("Verdana", 70), new SolidBrush(Color.DarkRed), 30, 30); for(xpos = 0; xpos < xres; xpos += (int)(sc.dpmmX*10.0)) { Point p1 = new Point(xpos,0); Point p2 = new Point(xpos,yres); gfx.DrawLine(pen, p1, p2); } for (ypos = 0; ypos < yres; ypos += (int)(sc.dpmmY*10.0)) { Point p1 = new Point(0, ypos); Point p2 = new Point(xres, ypos); gfx.DrawLine(pen, p1, p2); } } } PrintLayer(m_calibimage, SLICE_CALIBRATION, SLICE_CALIBRATION); }
private UVDLPApp() { m_appconfig = new AppConfig(); m_printerinfo = new MachineConfig(); m_buildparms = new SliceBuildConfig(); m_deviceinterface = new DeviceInterface(); m_buildmgr = new BuildManager(); m_slicer = new Slicer(); m_slicer.Slice_Event += new Slicer.SliceEvent(SliceEv); //m_flexslice = new FlexSlice(); m_gcode = new GCodeFile(""); // create a blank gcode to start with m_supportconfig = new SupportConfig(); m_supportgenerator = new SupportGenerator(); m_supportgenerator.SupportEvent+= new SupportGeneratorEvent(SupEvent); CSG.Instance().CSGEvent += new CSG.CSGEventDel(CSGEvent); m_proj_cmd_lst = new prjcmdlst(); m_plugins = new List<PluginEntry>(); // list of user plug-ins m_undoer = new Undoer(); }
// standard scene slicing // this function takes the object, the slicing parameters, // and the output directory. it generates the object slices // and saves them in the directory public SliceFile Slice(SliceBuildConfig sp)//, Object3d obj) { // create new slice file m_sf = new SliceFile(sp); m_sf.m_modeltype = Slicing.SliceFile.ModelType.eScene; if (sp.export == false) { m_sf.m_mode = SliceFile.SFMode.eImmediate; } m_slicethread = new Thread(new ThreadStart(slicefunc)); m_slicethread.Start(); isslicing = true; return m_sf; }
//, Object3d obj) // slicing of special objects. this is done in immediate mode only. no thread needed public SliceFile Slice(SliceBuildConfig sp, SliceFile.ModelType modeltype) { int numslices = 0; string scenename = ""; switch (modeltype) { case SliceFile.ModelType.eScene: return Slice(sp); //break; case SliceFile.ModelType.eResinTest1: numslices = (int)(7.0 / sp.ZThick); scenename = "Test Model V1"; break; } m_sf = new SliceFile(sp); m_sf.m_modeltype = modeltype; m_sf.m_mode = SliceFile.SFMode.eImmediate; m_sf.NumSlices = numslices; SliceStarted(scenename, numslices); DebugLogger.Instance().LogRecord("Test model slicing started"); SliceCompleted(scenename, 0, numslices); return m_sf; }
public void CopyFrom(SliceBuildConfig source) { dpmmX = source.dpmmX; // dots per mm x dpmmY = source.dpmmY; // dots per mm y xres = source.xres; yres = source.yres; // the resolution of the output image ZThick = source.ZThick; // thickness of the z layer - slicing height layertime_ms = source.layertime_ms; // time to project image per layer in milliseconds firstlayertime_ms = source.firstlayertime_ms; blanktime_ms = source.blanktime_ms; plat_temp = source.plat_temp; // desired platform temperature in celsius // exportgcode = source.exportgcode; // export the gcode file when slicing exportsvg = source.exportsvg; // export the svg slices when building export = source.export; // export image slices when building m_headercode = source.m_headercode; // inserted at beginning of file m_footercode = source.m_footercode; // inserted at end of file m_preliftcode = source.m_preliftcode; // inserted between each slice m_postliftcode = source.m_postliftcode; // inserted between each slice m_preslicecode = source.m_preslicecode; // inserted before each slice m_mainliftcode = source.m_mainliftcode; // inserted before postlift and after prelift. its the main lift code liftdistance = source.liftdistance; direction = source.direction; numfirstlayers = source.numfirstlayers; XOffset = source.XOffset; YOffset = source.YOffset; slidetiltval = source.slidetiltval; antialiasing = source.antialiasing; usemainliftgcode = source.usemainliftgcode; liftfeedrate = source.liftfeedrate; liftretractrate = source.liftretractrate; aaval = source.aaval;// //m_generateautosupports = source.m_generateautosupports; m_exportopt = source.m_exportopt; m_flipX = source.m_flipX; m_flipY = source.m_flipY; m_notes = source.m_notes; m_resinprice = source.m_resinprice; }
/// <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 function will iterate through the optimized loops /// and determine if they are interior or exterior and tag them appropriately /// </summary> public void DetermineInteriorExterior(SliceBuildConfig config) { List<PolyLine3d> allsegments = new List<PolyLine3d>(); foreach (PolyLine3d pln in m_opsegs) { pln.tag = PolyLine3d.TAG_INTERIOR; // mark it as interior List<PolyLine3d> segments = pln.Split(); // split them, retaining the parent allsegments.AddRange(segments); } List<Line2d> lines2d = Get2dLines(config, allsegments); // 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 { // the first point is always an exterior - really? why? Point2d p1 = (Point2d)points[cnt]; if (p1.m_parent != null) { p1.m_parent.tag = PolyLine3d.TAG_EXTERIOR; // mark as exterior } // the second point could be an exterior or interior Point2d p2 = (Point2d)points[cnt + 1]; } } else // flag error { DebugLogger.Instance().LogRecord("Row y=" + y + " odd # of points = " + points.Count + " - Model may have holes"); } }// for y = startminY to endY }
public Bitmap RenderSlice(SliceBuildConfig sp) { // create a new bitmap that will be used to draw into //Bitmap bmp = new Bitmap(sp.xres, sp.yres); double scaler = 1.5; // specofy the scale factor if (sp.antialiasing == true) { scaler = sp.aaval; } else { scaler = 1.0; // no scaling } double sdpmmx = sp.dpmmX; // save the original dots per mm double sdpmmy = sp.dpmmY; sp.dpmmX *= scaler;// scaler them up. sp.dpmmY *= scaler; //Re-sample to a higher resolution so we can smooth later int ox, oy; ox = sp.xres; // save the original resolution oy = sp.yres; double xs, ys; xs = ((double)sp.xres) * scaler; // scale them up ys = ((double)sp.yres) * scaler; sp.xres = (int) xs; sp.yres = (int) ys; Bitmap bmp = new Bitmap(sp.xres, sp.yres); //Bitmap bmp = new Bitmap((int)xs,(int)ys); Graphics graph = Graphics.FromImage(bmp); Point pnt1 = new Point(); // create some points for drawing Point pnt2 = new Point(); Pen pen = new Pen(Color.White,1); graph.Clear(Color.Black); //convert all to 2d lines int hxres = sp.xres / 2; int hyres = sp.yres / 2; ArrayList lines2d = Get2dLines(sp); Render2dlines(graph, lines2d,sp); // find the x/y min/max MinMax_XY mm = 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 ArrayList intersecting = GetIntersecting2dYLines(y, lines2d); // get the list of point intersections ArrayList points = GetIntersectingPoints(y,intersecting); // sort the points in increasing x order //SortXIncreasing(points); points.Sort(); // draw the X-Spans (should be even number) // For a given pair of intersectin points // (Xi, Y), (Xj, Y) // −> Fill ceiling(Xi) to floor(Xj) 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]; pnt1.X = (int)(p1.x + sp.XOffset + hxres); pnt1.Y = (int)(p1.y + sp.YOffset + hyres); pnt2.X = (int)(p2.x + sp.XOffset + hxres); pnt2.Y = (int)(p2.y + sp.YOffset + hyres); graph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; graph.DrawLine(pen, pnt1.X,pnt1.Y, pnt2.X,pnt2.Y); } } else // flag error { DebugLogger.Instance().LogRecord("Row y=" + y + " odd # of points = " + points.Count+ " - Model may have holes"); } } //Rescale the image to re-sample it from a higher res to soften the lines with bicubic interpolation. sp.dpmmX = sdpmmx; sp.dpmmY = sdpmmy; sp.xres = ox; sp.yres = oy; if (sp.antialiasing == true) // we're using anti-aliasing here, so resize the image { return ReflectY(ResizeImage(bmp, new Size(ox, oy))); } else { return ReflectY(bmp); } //return bmp; }
/* private static Bitmap ResizeImage(Bitmap imgToResize, Size size) { try { Bitmap b = new Bitmap(size.Width, size.Height); using (Graphics g = Graphics.FromImage((Image)b)) { //g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.DrawImage(imgToResize, 0, 0, size.Width, size.Height); } return b; } catch { return null; } } */ /// <summary> /// This new slicing function renders into a pre-allocated bitmap /// </summary> /// <param name="sp"></param> /// <param name="bmp"></param> public void RenderSlice(SliceBuildConfig sp, ref Bitmap bmp) { try { Graphics graph = Graphics.FromImage(bmp); Point pnt1 = new Point(); // create some points for drawing Point pnt2 = new Point(); Pen pen = new Pen(UVDLPApp.Instance().m_appconfig.m_foregroundcolor, 1); //convert all to 2d lines int hxres = sp.xres / 2; int hyres = sp.yres / 2; ArrayList lines2d = Get2dLines(sp); if (lines2d.Count == 0) return; Render2dlines(graph, lines2d, sp); // find the x/y min/max MinMax_XY mm = 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 ArrayList intersecting = GetIntersecting2dYLines(y, lines2d); // get the list of point intersections ArrayList points = GetIntersectingPoints(y, intersecting); // sort the points in increasing x order //SortXIncreasing(points); points.Sort(); // draw the X-Spans (should be even number) // For a given pair of intersectin points // (Xi, Y), (Xj, Y) // −> Fill ceiling(Xi) to floor(Xj) 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]; pnt1.X = (int)(p1.x + sp.XOffset + hxres); pnt1.Y = (int)(p1.y + sp.YOffset + hyres); pnt2.X = (int)(p2.x + sp.XOffset + hxres); pnt2.Y = (int)(p2.y + sp.YOffset + hyres); //graph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; graph.DrawLine(pen, pnt1.X, pnt1.Y, pnt2.X, pnt2.Y); } } else // flag error { DebugLogger.Instance().LogRecord("Row y=" + y + " odd # of points = " + points.Count + " - Model may have holes"); } } } catch (Exception ex) { DebugLogger.Instance().LogError(ex.Message); } }
private void Render2dlines(Graphics g, ArrayList lines, SliceBuildConfig sp) { Point pnt1 = new Point(); // create some points for drawing Point pnt2 = new Point(); Pen pen = new Pen(Color.White, 1); //Brush //Pen p2 = new Pen( int hxres = sp.xres / 2; int hyres = sp.yres / 2; foreach(Line2d ln in lines) { Point2d p1 = (Point2d)ln.p1; Point2d p2 = (Point2d)ln.p2; pnt1.X = (int)(p1.x ) + sp.XOffset + hxres; pnt1.Y = (int)(p1.y ) + sp.YOffset + hyres; pnt2.X = (int)(p2.x ) + sp.XOffset + hxres; pnt2.Y = (int)(p2.y ) + sp.YOffset + hyres; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; g.DrawLine(pen, pnt1, pnt2); } }
private void Render2dlines(Graphics g, ArrayList lines, SliceBuildConfig sp) { try { Point pnt1 = new Point(); // create some points for drawing Point pnt2 = new Point(); //Pen pen = new Pen(Color.White, 1); Pen pen = new Pen(UVDLPApp.Instance().m_appconfig.m_foregroundcolor, 1); //Brush //Pen p2 = new Pen( int hxres = sp.xres / 2; int hyres = sp.yres / 2; foreach (Line2d ln in lines) { Point2d p1 = (Point2d)ln.p1; Point2d p2 = (Point2d)ln.p2; pnt1.X = (int)(p1.x) + sp.XOffset + hxres; pnt1.Y = (int)(p1.y) + sp.YOffset + hyres; pnt2.X = (int)(p2.x) + sp.XOffset + hxres; pnt2.Y = (int)(p2.y) + sp.YOffset + hyres; //g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; g.DrawLine(pen, pnt1, pnt2); } } catch (Exception ex) { DebugLogger.Instance().LogError(ex.Message); } }
private String m_preslicecode; // inserted before each slice #endregion Fields #region Constructors /* Copy constructor */ public SliceBuildConfig(SliceBuildConfig source) { CopyFrom(source); }
//alright, it looks like I'm going to have to code up a 2d scanline fill algorithm // I suppose the first step is to convert all the 3d-ish polyline points in this slice into // 2d polylines, then use those to implement the fill /// <summary> /// This new slicing function renders into a pre-allocated bitmap /// </summary> /// <param name="sp"></param> /// <param name="bmp"></param> public void RenderSlice(SliceBuildConfig sp, ref Bitmap bmp, bool outlineonly = false) { try { Graphics graph = Graphics.FromImage(bmp); Point pnt1 = new Point(); // create some points for drawing Point pnt2 = new Point(); // in the future, the forecolor and backcolor should be pulled from the slice profile, not the app config Pen pen = new Pen(UVDLPApp.Instance().m_appconfig.m_foregroundcolor, 1); //convert all to 2d lines int hxres = sp.xres / 2; int hyres = sp.yres / 2; List <Line2d> lines2d = Get2dLines(sp, m_segments); if (lines2d.Count == 0) { return; } if (sp.m_createoutlines && outlineonly) { RenderOutlines(graph, sp); } else { // this renders the outline of the object for a filled slice Render2dlines(graph, lines2d, sp); } // find the x/y min/max MinMax_XY mm = CalcMinMax_XY(lines2d); if (outlineonly) { pen.Dispose(); return; } // 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 = GetIntersecting2dYLines(y, lines2d); // get the list of point intersections List <Point2d> points = GetIntersectingPoints(y, intersecting); // sort the points in increasing x order points.Sort(); SortBackfaces(points); if (UVDLPApp.Instance().m_slicer.m_slicemethod == Slicer.eSliceMethod.eEvenOdd) { // draw the X-Spans (should be even number) // For a given pair of intersectin points // (Xi, Y), (Xj, Y) // −> Fill ceiling(Xi) to floor(Xj) 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]; pnt1.X = (int)(p1.x + sp.XOffset + hxres); pnt1.Y = (int)(p1.y + sp.YOffset + hyres); pnt2.X = (int)(p2.x + sp.XOffset + hxres); pnt2.Y = (int)(p2.y + sp.YOffset + hyres); //graph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; graph.DrawLine(pen, pnt1.X, pnt1.Y, pnt2.X, pnt2.Y); } } else // flag error { DebugLogger.Instance().LogRecord("Row y=" + y + " odd # of points = " + points.Count + " - Model may have holes"); } } else if (UVDLPApp.Instance().m_slicer.m_slicemethod == Slicer.eSliceMethod.eNormalCount) { Point2d p1 = null; Point2d p2 = null; int turncount = 0; if (points.Count != 0) { for (int cnt = 0; cnt < points.Count; cnt++) { if (points[cnt].m_backfacing) { if (turncount == 0) //p1 == null) { p1 = (Point2d)points[cnt]; } turncount++; } else { //if (turncount > 0) turncount--; if ((turncount == 0) && (p1 != null)) { p2 = (Point2d)points[cnt]; pnt1.X = (int)(p1.x + sp.XOffset + hxres); pnt1.Y = (int)(p1.y + sp.YOffset + hyres); pnt2.X = (int)(p2.x + sp.XOffset + hxres); pnt2.Y = (int)(p2.y + sp.YOffset + hyres); //graph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; graph.DrawLine(pen, pnt1.X, pnt1.Y, pnt2.X, pnt2.Y); p1 = p2; p2 = null; } } } if (turncount != 0)// flag error { DebugLogger.Instance().LogRecord("Row y=" + y + " non equal in/outs = " + turncount + " - Model may have holes"); } } } } //clean up pen.Dispose(); } catch (Exception ex) { DebugLogger.Instance().LogError(ex.Message); } }
// this function converts all the 3d polyines to 2d lines so we can process everything private ArrayList Get2dLines(SliceBuildConfig sp) { ArrayList lst = new ArrayList(); // this can be changed at some point to assume that the 3d polyline has more than 2 points // I'll need to do this when I want to properly generate inside / outside countours foreach (PolyLine3d ply in m_segments) { Line2d ln = new Line2d(); //get the 3d points of the line Point3d p3d1 = (Point3d)ply.m_points[0]; Point3d p3d2 = (Point3d)ply.m_points[1]; //convert them to 2d (probably should add an offset to center them) ln.p1.x = (int)(p3d1.x * sp.dpmmX);// +hxres; ln.p1.y = (int)(p3d1.y * sp.dpmmY);// +hyres; ln.p2.x = (int)(p3d2.x * sp.dpmmX);// +hxres; ln.p2.y = (int)(p3d2.y * sp.dpmmY);// +hyres; lst.Add(ln); } return lst; // return the list }
public void CopyFrom(SliceBuildConfig source) { dpmmX = source.dpmmX; // dots per mm x dpmmY = source.dpmmY; // dots per mm y xres = source.xres; yres = source.yres; // the resolution of the output image ZThick = source.ZThick; // thickness of the z layer - slicing height layertime_ms = source.layertime_ms; // time to project image per layer in milliseconds firstlayertime_ms = source.firstlayertime_ms; blanktime_ms = source.blanktime_ms; plat_temp = source.plat_temp; // desired platform temperature in celsius // exportgcode = source.exportgcode; // export the gcode file when slicing exportsvg = source.exportsvg; // export the svg slices when building export = source.export; // export image slices when building exportpng = source.exportpng; m_headercode = source.m_headercode; // inserted at beginning of file m_footercode = source.m_footercode; // inserted at end of file m_preslicecode = source.m_preslicecode; // inserted before each slice m_liftcode = source.m_liftcode; // its the main lift code liftdistance = source.liftdistance; direction = source.direction; numfirstlayers = source.numfirstlayers; XOffset = source.XOffset; YOffset = source.YOffset; slidetiltval = source.slidetiltval; antialiasing = source.antialiasing; usemainliftgcode = source.usemainliftgcode; liftfeedrate = source.liftfeedrate; bottomliftfeedrate = source.bottomliftfeedrate; liftretractrate = source.liftretractrate; aaval = source.aaval;// //m_generateautosupports = source.m_generateautosupports; m_exportopt = source.m_exportopt; m_flipX = source.m_flipX; m_flipY = source.m_flipY; m_notes = source.m_notes; m_resinprice = source.m_resinprice; selectedInk = source.selectedInk; m_createoutlines = source.m_createoutlines; m_outlinewidth_inset = source.m_outlinewidth_inset; m_outlinewidth_outset = source.m_outlinewidth_outset; if (source.inks != null) { inks = new Dictionary<string, InkConfig>(); foreach (KeyValuePair<string, InkConfig> entry in source.inks) { inks[entry.Key] = entry.Value; } } minExposure = source.minExposure; exposureStep = source.exposureStep; exportpreview = source.exportpreview; userParams = source.userParams; }
public void ShowCalibration(int xres, int yres, SliceBuildConfig sc) { // if (m_calibimage == null) // blank image is null, create it { m_calibimage = new Bitmap(xres,yres); // fill it with black using (Graphics gfx = Graphics.FromImage(m_calibimage)) using (SolidBrush brush = new SolidBrush(Color.Black)) { gfx.FillRectangle(brush, 0, 0, xres, yres); int xpos = 0, ypos = 0; Pen pen = new Pen(new SolidBrush(Color.Red)); for(xpos = 0; xpos < xres; xpos += (int)(sc.dpmmX*10.0)) { Point p1 = new Point(xpos,0); Point p2 = new Point(xpos,yres); gfx.DrawLine(pen, p1, p2); } for (ypos = 0; ypos < yres; ypos += (int)(sc.dpmmY*10.0)) { Point p1 = new Point(0, ypos); Point p2 = new Point(xres, ypos); gfx.DrawLine(pen, p1, p2); } } } PrintLayer(m_calibimage, SLICE_CALIBRATION, SLICE_CALIBRATION); }
private ZipFile m_zip; // for storing image slices #endregion Fields #region Constructors private UVDLPApp() { m_appconfig = new AppConfig(); m_printerinfo = new MachineConfig(); m_buildparms = new SliceBuildConfig(); m_deviceinterface = new DeviceInterface(); m_buildmgr = new BuildManager(); m_slicer = new Slicer(); m_slicer.Slice_Event += new Slicer.SliceEvent(SliceEv); m_flexslice = new FlexSlice(); m_gcode = new GCodeFile(""); // create a blank gcode to start with m_supportconfig = new SupportConfig(); m_supportgenerator = new SupportGenerator(); m_supportgenerator.SupportEvent+= new SupportGeneratorEvent(SupEvent); }
public bool LoadBuildSliceProfile(string filename) { m_buildparms = new SliceBuildConfig(); bool ret = m_buildparms.Load(filename); if (ret) { m_appconfig.m_cursliceprofilename = filename; m_appconfig.Save(m_apppath + m_pathsep + m_appconfigname);// this name doesn't change RaiseAppEvent(eAppEvent.eSliceProfileChanged, ""); } return ret; }
/// <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 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 = 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++) { //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; AddNewSupport(center.x, center.y, center.z, scnt++, null, lstsupports); //region.ply.m_derived. /*s.Create(null,(float)m_sc.fbrad, (float)m_sc.ftrad, (float)m_sc.hbrad, (float)m_sc.htrad, lz * .2f, lz * .6f, lz * .2f, 11); * s.Translate((float)center.x, (float)center.y, 0); * s.Name = "Support " + scnt; * s.SetColor(Color.Yellow); * scnt++; * lstsupports.Add(s); * RaiseSupportEvent(UV_DLP_3D_Printer.SupportEvent.eSupportGenerated, s.Name, s); */ } RaiseSupportEvent(UV_DLP_3D_Printer.SupportEvent.eCompleted, "Support Generation Completed", lstsupports); m_generating = false; } catch (Exception ex) { DebugLogger.Instance().LogError(ex); } }