public bool Save(string filename) { try { bool retval = false; XmlWriter xw = XmlWriter.Create(filename); m_filename = filename; xw.WriteStartDocument(); xw.WriteStartElement("MachineConfig"); xw.WriteElementString("FileVersion", FILE_VERSION.ToString()); xw.WriteElementString("DLP_X_Res", m_XDLPRes.ToString()); xw.WriteElementString("DLP_Y_Res", m_YDLPRes.ToString()); xw.WriteElementString("PlatformXSize", m_PlatXSize.ToString()); xw.WriteElementString("PlatformYSize", m_PlatYSize.ToString()); xw.WriteElementString("PlatformZSize", m_PlatZSize.ToString()); xw.WriteElementString("PixPermmX", m_Xpixpermm.ToString()); xw.WriteElementString("PixPermmY", m_Ypixpermm.ToString()); xw.WriteElementString("MaxXFeedRate", m_XMaxFeedrate.ToString()); xw.WriteElementString("MaxYFeedRate", m_YMaxFeedrate.ToString()); xw.WriteElementString("MaxZFeedRate", m_ZMaxFeedrate.ToString()); xw.WriteElementString("MonitorID", m_monitorid.ToString()); if (m_driverconfig.Save(xw)) { retval = true; } xw.WriteEndElement(); xw.WriteEndDocument(); xw.Close(); return(retval); } catch (Exception ex) { DebugLogger.Instance().LogRecord(ex.Message); return(false); } }
public void SaveGCodes() { try { String profilepath = Path.GetDirectoryName(m_filename); profilepath += UVDLPApp.m_pathsep; profilepath += Path.GetFileNameWithoutExtension(m_filename); //create the directory if it doesn't exist if (!Directory.Exists(profilepath)) { Directory.CreateDirectory(profilepath); } SaveFile(profilepath + UVDLPApp.m_pathsep + "start.gcode", m_headercode); SaveFile(profilepath + UVDLPApp.m_pathsep + "end.gcode", m_footercode); SaveFile(profilepath + UVDLPApp.m_pathsep + "prelift.gcode", m_preliftcode); SaveFile(profilepath + UVDLPApp.m_pathsep + "postlift.gcode", m_postliftcode); SaveFile(profilepath + UVDLPApp.m_pathsep + "preslice.gcode", m_preslicecode); } catch (Exception ex) { DebugLogger.Instance().LogError(ex.Message); } }
/// <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); } }
public void DoAppStartup() { m_dispmgr = DisplayManager.Instance();// initialze the displays m_apppath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); //get the path separater if (RunningPlatform() == Platform.Windows) { m_pathsep = "\\"; } else { m_pathsep = "/"; } // define some default paths m_PathMachines = m_apppath + m_pathsep + "Machines"; // use full paths - SHS m_PathProfiles = m_apppath + m_pathsep + "Profiles"; // set up directories if they don't exist if (!Directory.Exists(m_PathMachines)) { Utility.CreateDirectory(m_PathMachines); } if (!Directory.Exists(m_PathProfiles)) { Utility.CreateDirectory(m_PathProfiles); } if (!m_appconfig.Load(m_apppath + m_pathsep + m_appconfigname)) // use full path - SHS { m_appconfig.CreateDefault(); m_appconfig.Save(m_apppath + m_pathsep + m_appconfigname); // use full path - SHS } // this will check and make sure the default machines have been created CheckAndCreateDefaultMachines(); //load the current machine configuration file if (!m_printerinfo.Load(m_appconfig.m_curmachineeprofilename)) { // m_printerinfo.Save(m_appconfig.m_curmachineeprofilename); DebugLogger.Instance().LogError("Cannot Load Machine Profile " + m_appconfig.m_curmachineeprofilename); } // machine configuration was just loaded here. RaiseAppEvent(eAppEvent.eMachineTypeChanged, ""); // notify the gui to set up correctly //load the projector command list if (!LoadProjectorCommands(m_appconfig.ProjectorCommandsFile)) { SaveProjectorCommands(m_appconfig.ProjectorCommandsFile); } //load the current slicing profile if (!m_buildparms.Load(m_appconfig.m_cursliceprofilename)) { m_buildparms.CreateDefault(); m_buildparms.Save(m_appconfig.m_cursliceprofilename); } // set up the drivers SetupDriver(); //SetupDriverProjector(); // load the support configuration if (!LoadSupportConfig(m_appconfig.SupportConfigName)) { SaveSupportConfig(m_appconfig.SupportConfigName); } //load the license keys LoadLicenseKeys(); //look for plug-ins and validate licensing ScanForPlugins(); // validate those loaded plugins against license keys CheckLicensing(); // initialize the plugins, the main form will send a secondary init after the main app gui is created PerformPluginCommand("InitCommand", true); m_sc = new ServerContact(); m_sc.ServerContactEvenet += new ServerContact.Servercontacted(m_sc_ServerContactEvent); m_sc.UpdateRegInfo(); m_undoer.RegisterCallback(); }
//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, m_segments); 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(); 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"); } } } } } catch (Exception ex) { DebugLogger.Instance().LogError(ex.Message); } }
static void Main() { Application.EnableVisualStyles(); Application.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; SetDefaultCulture(System.Globalization.CultureInfo.InvariantCulture); Application.SetCompatibleTextRenderingDefault(false); //init the app object UVDLPApp.Instance().DoAppStartup(); // start the app and load the plug-ins //iterate through the plugins bool showlicensedialog = false; bool nosplash = false; //iterate through all plugins, // if they are un-licensed and enabled - show licensing dialog. foreach (PluginEntry pe in UVDLPApp.Instance().m_plugins) { if (pe.m_licensed == false && pe.m_enabled == true) // if we don't have a license, and it's marked enabled { showlicensedialog = true; } int options = pe.m_plugin.GetInt("Options"); if (options != -1 && pe.m_enabled == true) // check to see if this plugin has options { if ((options & PluginOptions.OPTION_TIMED_TRIAL) != 0) // check for timed trial bit { // check for trial version //start trial version if (!CheckTrial(pe)) { //disable the plug-in pe.m_enabled = false; //exit? Application.Exit(); return; } } if ((options & PluginOptions.OPTION_NOSPLASH) != 0) { nosplash = true; } } } if (showlicensedialog == true) { frmPluginManager pim = new frmPluginManager(); pim.ShowDialog(); } try { #if !DEBUG // no splash screen under debug release if (!nosplash) { frmSplash splash = new frmSplash(); // should pull from a licensed plug-in if need-be splash.Show(); } #endif Application.Run(new frmMain2()); } catch (Exception ex) { DebugLogger.Instance().LogError(ex); } }
public void DoAppStartup() { m_dispmgr = DisplayManager.Instance();// initialze the displays m_apppath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); //get the path separater if (RunningPlatform() == Platform.Windows) { m_pathsep = "\\"; } else { m_pathsep = "/"; } // define some default paths m_PathMachines = m_apppath + m_pathsep + "Machines"; // use full paths - SHS m_PathProfiles = m_apppath + m_pathsep + "Profiles"; // set up directories if they don't exist if (!Directory.Exists(m_PathMachines)) { Utility.CreateDirectory(m_PathMachines); } if (!Directory.Exists(m_PathProfiles)) { Utility.CreateDirectory(m_PathProfiles); } if (!m_appconfig.Load(m_apppath + m_pathsep + m_appconfigname)) // use full path - SHS { m_appconfig.CreateDefault(); m_appconfig.Save(m_apppath + m_pathsep + m_appconfigname); // use full path - SHS } // this will check and make sure the default machines have been created CheckAndCreateDefaultMachines(); //load the current machine configuration file if (!m_printerinfo.Load(m_appconfig.m_curmachineeprofilename)) { // m_printerinfo.Save(m_appconfig.m_curmachineeprofilename); DebugLogger.Instance().LogError("Cannot Load Machine Profile " + m_appconfig.m_curmachineeprofilename); } // machine configuration was just loaded here. RaiseAppEvent(eAppEvent.eMachineTypeChanged, ""); // notify the gui to set up correctly //load the projector command list if (!LoadProjectorCommands(m_appconfig.ProjectorCommandsFile)) { SaveProjectorCommands(m_appconfig.ProjectorCommandsFile); } //load the current slicing profile if (!m_buildparms.Load(m_appconfig.m_cursliceprofilename)) { m_buildparms.CreateDefault(); m_buildparms.Save(m_appconfig.m_cursliceprofilename); } else { m_buildparms.CreateDefault(); m_buildparms.Load(m_appconfig.m_cursliceprofilename); } // set up the drivers SetupDriver(); //SetupDriverProjector(); // load the support configuration if (!LoadSupportConfig(m_appconfig.SupportConfigName)) { SaveSupportConfig(m_appconfig.SupportConfigName); } //load the license keys LoadLicenseKeys(); //look for plug-ins and validate licensing ScanForPlugins(); //look for 'lite' plugins ScanForPluginsLite(); // validate those loaded plugins against license keys CheckLicensing(); // initialize the plugins, the main form will send a secondary init after the main app gui is created PerformPluginCommand("InitCommand", true); m_sc = new ServerContact(); m_sc.ServerContactEvenet += new ServerContact.Servercontacted(m_sc_ServerContactEvent); //contacting Server twise?? commenting this out for now //m_sc.UpdateRegInfo(); m_undoer.RegisterCallback(); // pack all 2d gl images //m_2d_graphics.GenereteUserTexture(); //load Rsource files //this is not good way to load resource files. but the problem is visual studio cant generate auto-generation code for names with dot "." resman = new ResourceManager("UV_DLP_3D_Printer.Resource.en", typeof(UVDLPApp).Assembly); cul = CultureInfo.CreateSpecificCulture(""); if (UVDLPApp.Instance().m_appconfig.m_Selected_Language == "es") { resman = new ResourceManager("UV_DLP_3D_Printer.Resource.es", typeof(UVDLPApp).Assembly); cul = CultureInfo.CreateSpecificCulture(""); } else if (UVDLPApp.Instance().m_appconfig.m_Selected_Language == "en") { resman = new ResourceManager("UV_DLP_3D_Printer.Resource.en", typeof(UVDLPApp).Assembly); cul = CultureInfo.CreateSpecificCulture(""); } else { resman = new ResourceManager("UV_DLP_3D_Printer.Resource.en", typeof(UVDLPApp).Assembly); cul = CultureInfo.CreateSpecificCulture(""); } }
/* * This is the thread that controls the build process * it needs to read the lines of gcode, one by one * send them to the printer interface, * wait for the printer to respond, * and also wait for the layer interval timer */ void BuildThread() { int now = GetTimerValue(); int nextlayertime = 0; int sltime = -1, bltime = -1; while (m_running) { try { //Thread.Sleep(1); // sleep for 1 ms max Thread.Sleep(0); // sleep for 1 ms max switch (m_state) { case BuildManager.STATE_START: //start things off, reset some variables RaiseStatusEvent(eBuildStatus.eBuildStarted, "Build Started"); m_state = BuildManager.STATE_DO_NEXT_LAYER; // go to the first layer m_gcodeline = 0; // set the start line m_curlayer = 0; m_printstarttime = new DateTime(); break; case BuildManager.STATE_WAITING_FOR_LAYER: //check time var if (GetTimerValue() >= nextlayertime) { // DebugLogger.Instance().LogInfo("elapsed Layer time: " + GetTimerValue().ToString()); // DebugLogger.Instance().LogInfo("Diff = " + (GetTimerValue() - nextlayertime).ToString()); m_state = BuildManager.STATE_DO_NEXT_LAYER; // move onto next layer } break; case BuildManager.STATE_IDLE: // do nothing break; case BuildManager.STATE_DO_NEXT_LAYER: //check for done if (m_gcodeline >= m_gcode.Lines.Length) { //we're done.. m_state = BuildManager.STATE_DONE; continue; } string line = ""; // if the driver reports we're ready for the next command, or // if we choose to ignore the driver ready status if (UVDLPApp.Instance().m_deviceinterface.ReadyForCommand() || (UVDLPApp.Instance().m_appconfig.m_ignoreGCrsp == true)) { // go through the gcode, line by line line = m_gcode.Lines[m_gcodeline++]; } else { continue; // device is not ready } line = line.Trim(); if (line.Length > 0) // if the line is not blank { // send the line, whether or not it's a comment // should check to see if the firmware is ready for another line UVDLPApp.Instance().m_deviceinterface.SendCommandToDevice(line + "\r\n"); // if the line is a comment, parse it to see if we need to take action if (line.Contains("<Delay> ")) // get the delay { nextlayertime = GetTimerValue() + getvarfromline(line); //DebugLogger.Instance().LogInfo("Next Layer time: " + nextlayertime.ToString()); m_state = STATE_WAITING_FOR_LAYER; continue; } else if (line.Contains("<DispCmd>")) // display command { PerformDisplayCommand(line); } else if (line.Contains("<Slice> ")) //get the slice number { int layer = getvarfromline(line); int curtype = BuildManager.SLICE_NORMAL; // assume it's a normal image to begin with Bitmap bmp = null; if (layer == SLICE_BLANK) { if (m_blankimage == null) // blank image is null, create it { MakeBlank(m_sf.XRes, m_sf.YRes); } bmp = m_blankimage; curtype = BuildManager.SLICE_BLANK; bltime = GetTimerValue(); //DebugLogger.Instance().LogInfo("Showing Blank image at :" + bltime.ToString()); if (sltime != -1 && bltime != -1) { DebugLogger.Instance().LogInfo("Time between Blank and Slice :" + (bltime - sltime).ToString()); } } else if (layer == SLICE_SPECIAL) // plugins can override special images by named resource { // get the special image from the plugin (no caching for now..) string special = GetSpecialName(line); bmp = UVDLPApp.Instance().GetPluginImage(special); if (bmp == null) // no special image, even though it's specified.. { if (m_blankimage == null) // blank image is null, create it { MakeBlank(m_sf.XRes, m_sf.YRes); } bmp = m_blankimage; } curtype = BuildManager.SLICE_BLANK; } else { m_curlayer = layer; bmp = m_sf.GetSliceImage(m_curlayer); // get the rendered image slice or load it if already rendered if (bmp == null) { DebugLogger.Instance().LogError("Buildmanager bitmap is null layer = " + m_curlayer + " "); } sltime = GetTimerValue(); //DebugLogger.Instance().LogInfo("Showing Slice image at :" + sltime.ToString()); if (sltime != -1 && bltime != -1) { DebugLogger.Instance().LogInfo("Time between slice and blank :" + (sltime - bltime).ToString()); } } //raise a delegate so the main form can catch it and display layer information. if (PrintLayer != null) { PrintLayer(bmp, m_curlayer, curtype); } } } break; case BuildManager.STATE_DONE: try { m_running = false; m_state = BuildManager.STATE_IDLE; StopBuildTimer(); DateTime endtime = new DateTime(); double totalminutes = (endtime - m_printstarttime).TotalMinutes; m_printing = false; // mark printing doe //raise done message RaiseStatusEvent(eBuildStatus.eBuildStatusUpdate, "Build 100% Completed"); RaiseStatusEvent(eBuildStatus.eBuildCompleted, "Build Completed"); } catch (Exception ex) { DebugLogger.Instance().LogError(ex.StackTrace); } break; } } catch (Exception ex) { DebugLogger.Instance().LogError(ex.StackTrace); } } }
/* * This is the thread that controls the build process * it needs to read the lines of gcode, one by one * send them to the printer interface, * wait for the printer to respond, * and also wait for the layer interval timer */ void BuildThread() { int now = GetTimerValue(); int nextlayertime = 0; int sltime = -1, bltime = -1; while (m_running) { try { Thread.Sleep(0); // sleep for 1 ms max switch (m_state) { case BuildManager.STATE_START: //start things off, reset some variables RaiseStatusEvent(eBuildStatus.eBuildStarted, "Build Started"); m_state = BuildManager.STATE_DO_NEXT_COMMAND; // go to the first layer UVDLPApp.Instance().m_deviceinterface.SetReady(true); // say we're ready m_gcodeline = 0; // set the start line m_curlayer = 0; m_printstarttime = new DateTime(); break; case BuildManager.STATE_WAITING_FOR_DELAY: // general delay statement //check time var if (GetTimerValue() >= nextlayertime) { m_state = BuildManager.STATE_DO_NEXT_COMMAND; // move onto next layer } else { Thread.Sleep(1); // sleep for 1 ms to eliminate unnecessary cpu usage. } break; case BuildManager.STATE_IDLE: // do nothing break; case BuildManager.STATE_WAIT_DISPLAY: // we're waiting on the display to tell us we're done // this is used in the LaserSLA plugin, the normal DLP mode uses just a simple <Delay> command //do nothing break; case BuildManager.STATE_DO_NEXT_COMMAND: //check for done if (m_gcodeline >= m_gcode.Lines.Length) { //we're done.. m_state = BuildManager.STATE_DONE; continue; } string line = ""; // if the driver reports we're ready for the next command, or // if we choose to ignore the driver ready status if (UVDLPApp.Instance().m_deviceinterface.ReadyForCommand() || (UVDLPApp.Instance().m_appconfig.m_ignore_response == true)) { // go through the gcode, line by line line = m_gcode.Lines[m_gcodeline++]; #if (DEBUG) DebugLogger.Instance().LogInfo("Building : " + line); #endif } else { continue; // device is not ready } line = line.Trim(); if (line.Length > 0) // if the line is not blank { // send the line, whether or not it's a comment - this is for a reason.... // should check to see if the firmware is ready for another line UVDLPApp.Instance().m_deviceinterface.SendCommandToDevice(line + "\r\n"); // if the line is a comment, parse it to see if we need to take action if (line.ToLower().Contains("<delay> ")) // get the delay { nextlayertime = GetTimerValue() + getvarfromline(line); m_state = STATE_WAITING_FOR_DELAY; continue; } else if (line.ToLower().Contains("<dispcmd>")) // display command { PerformDisplayCommand(line); } else if (line.ToLower().Contains("<waitfordisplay>")) // wait for display to be done { m_state = BuildManager.STATE_WAIT_DISPLAY; } else if (line.ToLower().Contains("<auxcmd>")) //auxillary command to run a pre-defined sequence { PerformAuxCommand(line); } else if (line.ToLower().Contains("<slice> ")) //get the slice number { int layer = getvarfromline(line); int curtype = BuildManager.SLICE_NORMAL; // assume it's a normal image to begin with Bitmap bmp = null; bool isoutline = false; if (layer == SLICE_BLANK) { MakeBlank(m_sf.XRes, m_sf.YRes); bmp = m_blankimage; curtype = BuildManager.SLICE_BLANK; bltime = GetTimerValue(); } else if (layer == SLICE_SPECIAL) // plugins can override special images by named resource { // get the special image from the plugin (no caching for now..) string special = GetSpecialName(line); bmp = UVDLPApp.Instance().GetPluginImage(special); bmp.Tag = BuildManager.SLICE_SPECIAL; if (bmp == null) // no special image, even though it's specified.. { MakeBlank(m_sf.XRes, m_sf.YRes); bmp = m_blankimage; } curtype = BuildManager.SLICE_BLANK; } else if (layer == SLICE_OUTLINE) { isoutline = true; // we're rendering the layer in an outline image // get the curlayer from the line m_curlayer = outlinelayer; if (m_sf != null) { bmp = m_sf.GetSliceImage(m_curlayer, true); // get the rendered image slice or load it if already rendered if (bmp == null) { DebugLogger.Instance().LogError("Buildmanager bitmap is null layer = " + m_curlayer + " "); } else // not null { bmp.Tag = BuildManager.SLICE_NORMAL; // set the tag to normal so it is destroyed } } else { DebugLogger.Instance().LogWarning("Slice File is null during build and slice image is specified"); } sltime = GetTimerValue(); } else { m_curlayer = layer; if (m_sf != null) { bmp = m_sf.GetSliceImage(m_curlayer); // get the rendered image slice or load it if already rendered if (bmp == null) { DebugLogger.Instance().LogError("Buildmanager bitmap is null layer = " + m_curlayer + " "); } else // not null { bmp.Tag = BuildManager.SLICE_NORMAL; } } else { DebugLogger.Instance().LogWarning("Slice File is null during build and slice image is specified"); } sltime = GetTimerValue(); } // if a pause is requested, stop here... if (m_pause_request == true) { m_pause_request = false; ImplementPause(); // if the slice is blank, continue on to display it // if it's a new image slice (non-blank) continue the loop to go to the next state if (curtype != BuildManager.SLICE_BLANK) { continue; } } //raise a delegate so the main form can catch it and display layer information. if (PrintLayer != null) { PrintLayer(bmp, m_curlayer, curtype); } // make sure we raise this event only once if (!isoutline) { RaiseStatusEvent(eBuildStatus.eLayerCompleted, "Completed Layer"); } } } break; case BuildManager.STATE_DONE: try { m_running = false; m_state = BuildManager.STATE_IDLE; StopBuildTimer(); DateTime endtime = new DateTime(); double totalminutes = (endtime - m_printstarttime).TotalMinutes; m_printing = false; // mark printing doe //raise done message RaiseStatusEvent(eBuildStatus.eBuildStatusUpdate, "Build 100% Completed"); RaiseStatusEvent(eBuildStatus.eBuildCompleted, "Build Completed"); } catch (Exception ex) { DebugLogger.Instance().LogError(ex.StackTrace); } break; } } catch (Exception ex) { DebugLogger.Instance().LogError(ex.StackTrace); } } }
/// <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); } }
private void slicefunc() { try { MinMax mm = UVDLPApp.Instance().Engine3D.CalcSceneExtents(); int numslices = CalcNumSlices(mm.m_max, m_sf.m_config.ZThick); float curz = (float)(m_sf.m_config.ZThick / 2.0); // start at half slice thickness int c = 0; string scenename = UVDLPApp.Instance().SceneFileName; // a little housework here... foreach (Object3d obj in UVDLPApp.Instance().Engine3D.m_objects) { obj.FindMinMax(); } 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... } // if we're actually exporting something here, iterate through slices for (c = 0; c < numslices; c++) { List <PolyLine3d> lstintersections = null; if (m_sf.m_config.exportsvg != 0) { lstintersections = new List <PolyLine3d>(); } Bitmap savebm = SliceImmediate(curz, lstintersections); Bitmap outlinebm = null; //check to see if we're rendering the outline BM too if (m_sf.m_config.m_createoutlines == true) { outlinebm = SliceImmediate(curz, lstintersections, true); } if (m_cancel || (savebm == null)) { isslicing = false; m_cancel = false; //restore the original sizes //m_sf.m_config.CopyFrom(m_saved); RaiseSliceEvent(eSliceEvent.eSliceCancelled, c, numslices); return; } 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, lstintersections); if (m_sf.m_config.m_createoutlines == true) // make sure we export the slice too { LayerSliced(scenename, c, numslices, outlinebm, lstintersections, true); } } // 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 trys to join together the short line segments into /// a set of longer 3d polyines /// The goal here is to determine the interior and exterior lines /// This is going to help us do several things: /// 1) import/export SVG/CLI files /// 2) determine overlapping boundaries for better self-intersecting models /// 3) determine overhangs - by detemining if polylines from other layers intersect vertically or are encapsulated. /// /// The first pass of this algorithm may have to be N^2 search, I'll try /// to change it to log(N) or N as I go along /// </summary> /// public void Optimize() { try { // copy all the polylines in segments into a list List <PolyLine3d> allseg = new List <PolyLine3d>(); //create the final optimize segment list m_opsegs = new List <PolyLine3d>(); // copy the list and clone the polyline segments foreach (PolyLine3d pl in m_segments) { allseg.Add(new PolyLine3d(pl)); } // gotta keep track of lines to remove List <PolyLine3d> removelist = new List <PolyLine3d>(); bool done = false; // matchcount is a counter that tracks how many endpoints we've matched this trip around int matchcount = 0; while (!done) { // set the current line to be the first polyline segement PolyLine3d curline = allseg[0]; //iterate through all the line segments in allsegs for (int cnt = 0; cnt < allseg.Count; cnt++) { PolyLine3d pl = allseg[cnt]; if (cnt != 0) // the first polyline is the one we're always trying to match { // if the last point in the current polyline matches the first point // in the line we're testing, add the second point of the line we're testing // to the end of the current line if (curline.m_points[curline.m_points.Count - 1].Matches(pl.m_points[0])) // case 2 { //if ((curline.m_derived.SharesEdge(pl.m_derived))) { curline.m_points.AddRange(pl.m_points); removelist.Add(pl); // add the test line to the list of lines to remove, now that we've used it matchcount++; } } else if (curline.m_points[curline.m_points.Count - 1].Matches(pl.m_points[pl.m_points.Count - 1])) // case 4 last point matches last { // && (curline.m_derived.SharesEdge(pl.m_derived)) pl.m_points.Reverse(); curline.m_points.AddRange(pl.m_points); removelist.Add(pl); matchcount++; } else if (curline.m_points[0].Matches(pl.m_points[pl.m_points.Count - 1])) //case 1 { curline.m_points.Reverse(); pl.m_points.Reverse(); curline.m_points.AddRange(pl.m_points); removelist.Add(pl); matchcount++; } else if (curline.m_points[0].Matches(pl.m_points[0])) // case 3 { curline.m_points.Reverse(); curline.m_points.AddRange(pl.m_points); removelist.Add(pl); matchcount++; } } } // now remove all the matched segments from all segment list foreach (PolyLine3d seg in removelist) { allseg.Remove(seg); } removelist.Clear(); if (matchcount > 0) { matchcount = 0; // reset the match counter } else { // the current segment is not longer matching // add it to the final list of optimized segments m_opsegs.Add(curline); //and remove it from the list of all segments allseg.Remove(curline); //check for end condition if (allseg.Count == 0) { done = true; } } } } catch (Exception ex) { DebugLogger.Instance().LogError(ex.Message); } RemoveDoublePoints(); // make really clean }
void BuildStatus(eBuildStatus printstat, string mess) { // displays the print status if (InvokeRequired) { BeginInvoke(new MethodInvoker(delegate() { BuildStatus(printstat, mess); })); } else { String message = ""; switch (printstat) { case eBuildStatus.eBuildPaused: message = "Print Paused"; SetButtonStatuses(); SetMainMessage(message); DebugLogger.Instance().LogRecord(message); break; case eBuildStatus.eBuildResumed: message = "Print Resumed"; SetButtonStatuses(); SetMainMessage(message); DebugLogger.Instance().LogRecord(message); break; case eBuildStatus.eBuildCancelled: message = "Print Cancelled"; SetButtonStatuses(); ctlMachineControl1.BuildStopped(); SetMainMessage(message); DebugLogger.Instance().LogRecord(message); break; case eBuildStatus.eLayerCompleted: message = "Layer Completed"; break; case eBuildStatus.eBuildCompleted: message = "Print Completed"; SetButtonStatuses(); ctlMachineControl1.BuildStopped(); MessageBox.Show("Build Completed"); SetMainMessage(message); DebugLogger.Instance().LogRecord(message); break; case eBuildStatus.eBuildStarted: message = "Print Started"; SetButtonStatuses(); ctlMachineControl1.BuildStarted(); // if the current machine type is a UVDLP printer, make sure we can show the screen if (UVDLPApp.Instance().m_printerinfo.m_machinetype == MachineConfig.eMachineType.UV_DLP) { if (!m_frmdlp.ShowDLPScreen()) { MessageBox.Show("Monitor " + UVDLPApp.Instance().m_printerinfo.m_monitorconfig.Monitorid + " not found, cancelling build", "Error"); UVDLPApp.Instance().m_buildmgr.CancelPrint(); } } SetMainMessage(message); DebugLogger.Instance().LogRecord(message); break; case eBuildStatus.eBuildStatusUpdate: // a message from the build manager has arrived this.SetTimeMessage(mess); break; } } }
/* * This handles specific events triggered by the app */ private void AppEventDel(eAppEvent ev, String Message) { if (InvokeRequired) { BeginInvoke(new MethodInvoker(delegate() { AppEventDel(ev, Message); })); } else { switch (ev) { case eAppEvent.eModelNotLoaded: DebugLogger.Instance().LogRecord(Message); break; case eAppEvent.eModelRemoved: //the current model was removed DebugLogger.Instance().LogRecord(Message); UpdateSceneInfo(); UVDLPApp.Instance().m_engine3d.UpdateLists(); ctl3DView1.UpdateView(); //DisplayFunc(); break; case eAppEvent.eSlicedLoaded: // update the gui to view DebugLogger.Instance().LogRecord(Message); int totallayers = UVDLPApp.Instance().m_slicefile.NumSlices; ctl3DView1.SetNumLayers(totallayers); ctlSliceView1.SetNumLayers(totallayers); //show the slice in the slice view ViewLayer(0, null, BuildManager.SLICE_NORMAL); break; case eAppEvent.eGCodeLoaded: DebugLogger.Instance().LogRecord(Message); ctlGcodeView1.Text = UVDLPApp.Instance().m_gcode.RawGCode; break; case eAppEvent.eGCodeSaved: DebugLogger.Instance().LogRecord(Message); break; case eAppEvent.eModelAdded: UpdateSceneInfo(); UVDLPApp.Instance().m_engine3d.UpdateLists(); //DisplayFunc(); ctl3DView1.UpdateView(); DebugLogger.Instance().LogRecord(Message); break; case eAppEvent.eSliceProfileChanged: SetTitle(); break; case eAppEvent.eMachineTypeChanged: // FIXFIX : activate SetupForMachineType on 3dview control SetupForMachineType(); SetTitle(); break; case eAppEvent.eShowBlank: showBlankDLP(); break; case eAppEvent.eShowCalib: showCalibrationToolStripMenuItem_Click(null, null); break; case eAppEvent.eShowDLP: m_frmdlp.ShowDLPScreen(); break; case eAppEvent.eHideDLP: m_frmdlp.HideDLPScreen(); break; case eAppEvent.eReDraw: // redraw the 3d display //DisplayFunc(); ctl3DView1.UpdateView(); UpdateSceneInfo(); break; case eAppEvent.eMachineConnected: showBlankDLP(); break; case eAppEvent.eMachineDisconnected: break; } } Refresh(); }
bool Load(XmlHelper xh) { bool retval = false; XmlNode mc = xh.m_toplevel; m_PlatXSize = xh.GetDouble(mc, "PlatformXSize", 102.0); m_PlatYSize = xh.GetDouble(mc, "PlatformYSize", 77.0); m_PlatZSize = xh.GetDouble(mc, "PlatformZSize", 100.0); m_XMaxFeedrate = xh.GetDouble(mc, "MaxXFeedRate", 100.0); m_YMaxFeedrate = xh.GetDouble(mc, "MaxYFeedRate", 100.0); m_ZMaxFeedrate = xh.GetDouble(mc, "MaxZFeedRate", 100.0); XRenderSize = xh.GetInt(mc, "XRenderSize", 1024); YRenderSize = xh.GetInt(mc, "YRenderSize", 768); m_OverrideRenderSize = xh.GetBool(mc, "OverrideRenderSize", false); MachineControls = xh.GetString(mc, "DisplayedControls", "XYZPG"); m_machinetype = (eMachineType)xh.GetEnum(mc, "MachineType", typeof(eMachineType), eMachineType.UV_DLP); m_multimontype = (eMultiMonType)xh.GetEnum(mc, "MultiMonType", typeof(eMultiMonType), eMultiMonType.eHorizontal); m_ip = xh.GetString(mc, "ip", "192.168.1.6"); var ComPortnodes = xh.FindAllChildElement(mc, "ComPortSettings"); foreach (XmlNode node in ComPortnodes) { serialComPort = xh.GetString(node, "PortName", "COM1"); serialBaudRate = xh.GetString(node, "Speed", "9600"); serialDataBits = xh.GetString(node, "Databits", "8"); serialParity = xh.GetString(node, "Parity", "0"); serialStopBits = xh.GetString(node, "Stopbits", "1"); } if (m_driverconfig.Load(xh, mc)) { retval = true; } //m_monitorconfig.Load(xh, mc); List <XmlNode> monitornodes = xh.FindAllChildElement(mc, "MonitorDriverConfig"); m_lstMonitorconfigs = new List <MonitorConfig>(); foreach (XmlNode node in monitornodes) { MonitorConfig monc = new MonitorConfig(); monc.Load(xh, node); m_lstMonitorconfigs.Add(monc); } if (m_lstMonitorconfigs.Count > 0) { // we need at least 1 monitor //m_monitorconfig = m_lstMonitorconfigs[0]; } else { DebugLogger.Instance().LogError("No monitor configurations found!"); } CalcPixPerMM(); //if we have a special render size, don't wipe it out... if (m_OverrideRenderSize == false) { CorrectMonitorConfig(); } userParams = new UserParameterList(); xh.LoadUserParamList(userParams); return(retval); }
/// <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 function sends commands to the projector(s) /// The format is <DispCmd> MonitorID , cmdname /// Monitor ID can be any monitor on the system, or ALL /// </summary> /// <param name="line"></param> private void PerformDisplayCommand(string line) { try { line = line.Replace(';', ' '); // remove comments line = line.Replace(')', ' '); // remove comments int bidx = line.IndexOf('>'); if (bidx == -1) { DebugLogger.Instance().LogError("Improperly formated display command"); return; } string ss1 = line.Substring(bidx + 1); string[] lines = ss1.Split(','); if (lines.Length != 2) { DebugLogger.Instance().LogError("Improperly formated display command"); return; } string monname = lines[0].Trim(); string cmdname = lines[1].Trim(); //get the command name ProjectorCommand pc = null; pc = UVDLPApp.Instance().m_proj_cmd_lst.FindByName(cmdname); if (pc == null) { DebugLogger.Instance().LogError("Could not find Display Command " + cmdname); return; } // get the monitor ID if (monname.Equals("All")) { //iterate through all configured monitors in machine monitor list foreach (MonitorConfig mc in UVDLPApp.Instance().m_printerinfo.m_lstMonitorconfigs) { SendProjCmd(mc, pc); } } else { MonitorConfig mc = UVDLPApp.Instance().m_printerinfo.FindMonitorByName(monname); if (mc != null) { SendProjCmd(mc, pc); } else { DebugLogger.Instance().LogError("Monitor ID " + monname + " not found"); return; } } // get the commands name //find the command in the projector command list // make sure the com port for the projector is open //send the command to the projector over serial } catch (Exception ex) { DebugLogger.Instance().LogError(ex); } }
private void slicefunc() { try { m_cancel = false; isslicing = true; MinMax mm = UVDLPApp.Instance().Engine3D.CalcSceneExtents(); int numslices = CalcNumSlices(mm.m_max, m_sf.m_config.ZThick); float curz = (float)(m_sf.m_config.ZThick / 2.0); // start at half slice thickness //int c = 0; string scenename = UVDLPApp.Instance().SceneFileName; // a little housework here... foreach (Object3d obj in UVDLPApp.Instance().Engine3D.m_objects) { obj.FindMinMax(); } 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 + (int)m_sf.m_config.m_bottom_layers); //m_sf.m_config.CopyFrom(m_saved); isslicing = false; return; // exit slicing, nothing more to do... } // if we're actually exporting something here, iterate through slices var t1 = DateTime.Now; for (int c = 0; c < numslices + m_sf.m_config.m_bottom_layers; c++) { if (!isslicing) { return; } if (m_cancel) { isslicing = false; m_cancel = false; RaiseSliceEvent(eSliceEvent.eSliceCancelled, c, numslices); return; } curz = (float)((m_sf.m_config.ZThick / 2.0) + c * m_sf.m_config.ZThick); List <PolyLine3d> lstintersections = null; if (m_sf.m_config.exportsvg != 0) { lstintersections = new List <PolyLine3d>(); } // where is this memory for the allocated bitmap being freed? using (Bitmap savebm = SliceImmediate(curz, lstintersections, c <= m_sf.m_config.m_bottom_layers)) { // check for cancel or error if (m_cancel || (savebm == null)) { isslicing = false; m_cancel = false; //restore the original sizes RaiseSliceEvent(eSliceEvent.eSliceCancelled, c, numslices); return; } //raise an event to say we've finished a main filled slice LayerSliced(scenename, c, numslices, savebm, lstintersections); //check to see if we're rendering the outline BM too if (m_sf.m_config.m_createoutlines == true) { //make sure to manage the memory using (Bitmap outlinebm = SliceImmediate(curz, lstintersections, true)) { if (outlinebm != null) { LayerSliced(scenename, c, numslices, outlinebm, lstintersections, true); } else { //Error rendering the outline bitmap? DebugLogger.Instance().LogError("Error rendering outline slice"); } } } // move the slice for the next layer } } //for (c = 0; c < numslices; c++) //{ //} var t2 = DateTime.Now - t1; // restore the original m_sf.m_config.CopyFrom(m_saved); SliceCompleted(scenename, numslices - 1, 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; } }
public override string Export(Stream stream, string filename) { m_stream = stream; if ((m_name == null) || (m_name.Length == 0)) { m_name = Path.GetFileNameWithoutExtension(filename); } if ((m_description == null) || (m_description.Length == 0)) { m_description = m_name; } try { ReportStart(); SliceBuildConfig config = UVDLPApp.Instance().m_buildparms; config.UpdateFrom(UVDLPApp.Instance().m_printerinfo); // make sure we've got the correct display size and PixPerMM values // write header WriteString("1"); // version WriteString(m_name); // scene name WriteString(m_description); // scene description WriteDouble(1 / config.dpmmX); // pixel size in mm WriteDouble(config.ZThick); // slice thickness WriteInt32(0); // base standoff layers (?) WriteInt32(0); // Number of base offset layers where extents are filled (?) WriteString("Reserved3"); WriteString("Reserved2"); WriteString("Reserved1"); // write slices int numslices = UVDLPApp.Instance().m_slicer.GetNumberOfSlices(config); WriteInt32(numslices); float zlev = (float)(config.ZThick * 0.5); int npix = config.xres * config.yres; int[] lbm = new int[npix]; // current slice int p; //Bitmap bm = new Bitmap(config.xres, config.yres, System.Drawing.Imaging.PixelFormat.Format32bppArgb); // working bitmap //Color savecol = UVDLPApp.Instance().m_appconfig.m_foregroundcolor; 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 } for (int c = 0; c < numslices; c++) { //bool layerneedssupport = false; if (CancelExport) { return("Info|Export operation canceled"); } ReportProgress(c * 100 / numslices); /*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.White; * sl.RenderSlice(config, ref bm);*/ Bitmap bm = UVDLPApp.Instance().m_slicer.SliceImmediate(zlev); zlev += (float)config.ZThick; 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); CrushSlice(lbm, config.xres, config.yres); } // write supports (currently not handled) WriteInt32(0); // zero supports } catch (Exception ex) { DebugLogger.Instance().LogError(ex); return("Error|Export terminated unexpectedly"); } return("Export|Export completed successfully"); }
private void SliceStarted(string scenename, int numslices) { if (m_sf.m_config.export == true) // if we're exporting { //exporting to cws file //get the name oif the scene file if (UVDLPApp.Instance().SceneFileName.Length == 0) { //MessageBox.Show("Please Save the Scene First Before Exporting Slices"); if (MessageBox.Show("The Scene must be saved before exporting slices", "Please Save Scene", MessageBoxButtons.OKCancel) == DialogResult.OK) { UVDLPApp.Instance().m_mainform.SaveScene(null, null); } //MessageBox.Show(en.Slicer_SliceStarted_Please_Save_the_Scene_First_Before_Exporting_Slices); CancelSlicing(); return; } if (m_sf.m_config.exportpng == true) { // if we're exporting png slices to disk as well, then make sure we have a directory to export them into try { string exportdirname = SliceFile.GetSliceFilePath(UVDLPApp.Instance().SceneFileName); if (!Directory.Exists(exportdirname)) // if the directory does not exist { //create the directory to export images into Directory.CreateDirectory(exportdirname); //create the /preview directory here? } } catch (Exception ex) { DebugLogger.Instance().LogError(ex); } } //if (!string.IsNullOrWhiteSpace(UVDLPApp.Instance().SceneFileName)) // check again to make sure we've really got a name if (UVDLPApp.Instance().SceneFileName != null && UVDLPApp.Instance().SceneFileName.Length > 0) // check again to make sure we've really got a name { //remove all the previous images first //remove the png slices SceneFile.Instance().RemoveResourcesFromFile(UVDLPApp.Instance().SceneFileName, "Slices", ".png"); SceneFile.Instance().RemoveResourcesBySection(UVDLPApp.Instance().SceneFileName, "Slices"); //remove the vector slices SceneFile.Instance().RemoveResourcesFromFile(UVDLPApp.Instance().SceneFileName, "VectorSlices", ".svg"); //remove any slice profile in the scene file SceneFile.Instance().RemoveResourcesFromFile(UVDLPApp.Instance().SceneFileName, "SliceProfile", ".slicing"); //create a memory stream to hold the slicing profile in memory MemoryStream ms = new MemoryStream(); //serialize the slciing profile into the memory stream string sliceprofilename = Path.GetFileNameWithoutExtension(UVDLPApp.Instance().m_buildparms.m_filename) + ".slicing"; UVDLPApp.Instance().m_buildparms.Save(ms, sliceprofilename); ms.Seek(0, SeekOrigin.Begin); // rewind //save the stream to the scene cws zip file SceneFile.Instance().AddSliceProfileToFile(UVDLPApp.Instance().SceneFileName, ms, sliceprofilename); // if we've saved this scene before, then we can save the images into it. Open it up for add } else { //no name? cancel slicing CancelSlicing(); } } RaiseSliceEvent(eSliceEvent.eSliceStarted, 0, numslices); }
/// <summary> /// Loads a model, adds it to the 3d engine to be shown, and raises an app event /// </summary> /// <param name="filename"></param> /// <returns></returns> public bool LoadModel(String filename) { try { ModelLoader ml = new ModelLoader(); if (SceneFileName.Length == 0) { SceneFileName = filename; // set it to be the first file loaded } List <Object3d> objs = ml.Load(filename); if (objs != null) { foreach (Object3d obj in objs) { obj.CenterOnPlatform(); m_engine3d.AddObject(obj); m_undoer.SaveAddition(obj); SelectedObject = obj; } UVDLPApp.Instance().m_engine3d.UpdateLists(); m_slicefile = null; // the slice file is not longer current RaiseAppEvent(eAppEvent.eModelAdded, "Model Loaded " + filename); /* * //now try to load the gcode file * String gcodefile = Path.GetFileNameWithoutExtension(filename) + ".gcode"; * String gcodepath = SliceFile.GetSliceFilePath(filename); * * String gpath = gcodepath + UVDLPApp.m_pathsep + gcodefile; * if (File.Exists(gpath)) * { * LoadGCode(gpath); * } * else // read the gcode from the zip file * { * String zpath = gcodepath + ".zip"; * if(File.Exists(zpath)) // make sure the file exists before we try to read it * { * Stream s = Utility.ReadFromZip(zpath, gcodefile); * if(s != null) * { * s.Seek(0, 0); // go to the beginning of the stream * byte []array = Utility.ReadFully(s); * string gc = System.Text.Encoding.ASCII.GetString(array); * m_gcode = new GCodeFile(gc); * RaiseAppEvent(eAppEvent.eGCodeLoaded, "GCode Loaded " + gcodefile); * } * else * { * DebugLogger.Instance().LogError("Could not load GCode from Zip " + zpath); * } * } * * } * if(m_gcode !=null) * { * int xres, yres, numslices; * xres = m_gcode.GetVar("Projector X Res"); * yres = m_gcode.GetVar("Projector Y Res"); * numslices = m_gcode.GetVar("Number of Slices"); * m_slicefile = new SliceFile(xres,yres,numslices); * m_slicefile.modelname = SelectedObject.m_fullname; * m_slicefile.m_config = null; //this can be null if we're loading it... * RaiseAppEvent(eAppEvent.eSlicedLoaded, "SliceFile Created"); * } * */ } else { RaiseAppEvent(eAppEvent.eModelNotLoaded, "Model " + filename + " Failed to load"); } return(objs != null); } catch (Exception ex) { DebugLogger.Instance().LogRecord(ex.Message); return(false); } }
/// <summary> /// This will be called when we're exporting /// </summary> /// <param name="scenename"></param> /// <param name="layer"></param> /// <param name="numslices"></param> /// <param name="bmp"></param> /// <param name="lstPoly"></param> private void LayerSliced(string scenename, int layer, int numslices, Bitmap bmp, List <PolyLine3d> lstintersections, bool outline = false) { string path = ""; try { // if (m_buildparms.exportimages) { // get the model name String modelname = scenename; String outlinename = ""; // strip off the file extension path = SliceFile.GetSliceFilePath(modelname); if (outline) { outlinename = "_outline"; } String imname = Path.GetFileNameWithoutExtension(modelname) + outlinename + String.Format("{0:0000}", layer) + ".bmp"; String imagename = path + UVDLPApp.m_pathsep + imname; // create a memory stream for this to save into bmp.Tag = BuildManager.SLICE_NORMAL; // mark it as normal MemoryStream ms = new MemoryStream(); bmp.Save(ms, ImageFormat.Bmp); ms.Seek(0, SeekOrigin.Begin); // seek back to beginning if (!m_cancel) // if we're not in the process of cancelling { SceneFile.Instance().AddSlice(UVDLPApp.Instance().SceneFileName, ms, imname); } if (m_sf.m_config.exportpng) { //imagename var img = (Image)bmp; img.Save(imagename, ImageFormat.Bmp); //bmp.Save(imagename); } if (lstintersections != null) { StreamWriter sw; imname = Path.GetFileNameWithoutExtension(modelname) + String.Format("{0:0000}", layer) + ".svg"; imagename = path + UVDLPApp.m_pathsep + imname; if (m_sf.m_config.exportsvg < 3) { Path2D vectorPath = new Path2D(lstintersections); sw = vectorPath.GenerateSVG(UVDLPApp.Instance().m_printerinfo.m_PlatXSize, UVDLPApp.Instance().m_printerinfo.m_PlatYSize, m_sf.m_config.exportsvg == 2); } else { Slice sl = new Slice(); sl.m_segments = lstintersections; sl.Optimize(); sw = GenerateSVG(sl.m_opsegs, m_sf.m_config.exportsvg == 4); } if (!m_cancel) { SceneFile.Instance().AddVectorSlice(UVDLPApp.Instance().SceneFileName, (MemoryStream)sw.BaseStream, imname); } } RaiseSliceEvent(eSliceEvent.eLayerSliced, layer, numslices); } } catch (Exception ex) { string s = ex.StackTrace; DebugLogger.Instance().LogError(ex.Message); } }
/// <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 * } */ /// <summary> /// This function trys to join together the short line segments into /// a set of longer 3d polyines /// The goal here is to determine the interior and exterior lines /// This is going to help us do several things: /// 1) import/export SVG/CLI files /// 2) determine overlapping boundaries for better self-intersecting models /// 3) determine overhangs - by detemining if polylines from other layers intersect vertically or are encapsulated. /// /// The first pass of this algorithm may have to be N^2 search, I'll try /// to change it to log(N) or N as I go along /// </summary> /// public void Optimize() { try { // copy all the polylines in segments into a list List <PolyLine3d> allseg = new List <PolyLine3d>(); //create the final optimize segment list m_opsegs = new List <PolyLine3d>(); // copy the list and clone the polyline segments foreach (PolyLine3d pl in m_segments) { if (!pl.m_points[0].Matches(pl.m_points[pl.m_points.Count - 1])) // discard sements with same beginning and end { allseg.Add(new PolyLine3d(pl)); } } // gotta keep track of lines to remove List <PolyLine3d> removelist = new List <PolyLine3d>(); bool done = false; // matchcount is a counter that tracks how many endpoints we've matched this trip around int matchcount = 0; while (!done) { // set the current line to be the first polyline segement PolyLine3d curline = allseg[0]; //iterate through all the line segments in allsegs for (int cnt = 0; cnt < allseg.Count; cnt++) { PolyLine3d pl = allseg[cnt]; if (cnt != 0) // the first polyline is the one we're always trying to match { // if the last point in the current polyline matches the first point // in the line we're testing, add the second point of the line we're testing // to the end of the current line if (curline.m_points[curline.m_points.Count - 1].Matches(pl.m_points[0])) // case 2 { //if ((curline.m_derived.SharesEdge(pl.m_derived))) { for (int i = 1; i < pl.m_points.Count; i++) { curline.m_points.Add(pl.m_points[i]); } removelist.Add(pl); // add the test line to the list of lines to remove, now that we've used it matchcount++; } } else if (curline.m_points[curline.m_points.Count - 1].Matches(pl.m_points[pl.m_points.Count - 1])) // case 4 last point matches last { // && (curline.m_derived.SharesEdge(pl.m_derived)) pl.m_points.Reverse(); for (int i = 1; i < pl.m_points.Count; i++) { curline.m_points.Add(pl.m_points[i]); } removelist.Add(pl); matchcount++; } /* -- SHS: case 1 and case 3 will change the first segment * I need it to calculate correct path direction * else if (curline.m_points[0].Matches(pl.m_points[pl.m_points.Count - 1])) //case 1 * { * curline.m_points.Reverse(); * pl.m_points.Reverse(); * for (int i=1; i<pl.m_points.Count; i++) * curline.m_points.Add(pl.m_points[i]); * removelist.Add(pl); * matchcount++; * } * else if (curline.m_points[0].Matches(pl.m_points[0])) // case 3 * { * curline.m_points.Reverse(); * for (int i = 1; i < pl.m_points.Count; i++) * curline.m_points.Add(pl.m_points[i]); * removelist.Add(pl); * matchcount++; * }*/ } } // now remove all the matched segments from all segment list foreach (PolyLine3d seg in removelist) { allseg.Remove(seg); } removelist.Clear(); if (matchcount > 0) { matchcount = 0; // reset the match counter } else { // the current segment is not longer matching // match curve direction based on normal such that the right side is inside the object. double curveDir = Math.Atan2(curline.m_points[1].y - curline.m_points[0].y, curline.m_points[1].x - curline.m_points[0].x); double normalDir = Math.Atan2(curline.m_derived.m_normal.y, curline.m_derived.m_normal.x); double dirDiff = curveDir - normalDir; if (dirDiff < 0) { dirDiff += 2 * Math.PI; // handle negative result } if ((dirDiff > 0) && (dirDiff < Math.PI)) { curline.m_points.Reverse(); // reverse curve direction to match normal } // add it to the final list of optimized segments m_opsegs.Add(curline); //and remove it from the list of all segments allseg.Remove(curline); //check for end condition if (allseg.Count == 0) { done = true; } } } } catch (Exception ex) { DebugLogger.Instance().LogError(ex.Message); } RemoveDoublePoints(); // make really clean }
/// <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; }
//licenses can be in a few states: // licensed and enabled - load the plugin and use it // licensed and disabled - do not use the plugin, do not initialize // un-licensed and enabled - prompt the user for license key, do not initialize it // un-licensed and disabled - ignore this plugin, keep entry for it, do not initialize public void ScanForPlugins() { // load the list of plugin states string picn = m_apppath + m_pathsep + "pluginconfig.cfg"; // plugin configuration name m_pluginstates.Load(picn); // get a list of dll's in this current directory // try to register them as a plug-in string[] filePaths = Directory.GetFiles(m_apppath, "*.dll"); foreach (String pluginname in filePaths) { string args = Path.GetFileNameWithoutExtension(pluginname); if (args.ToLower().StartsWith("pl")) { // located a dll that is a potential plugin Type ObjType = null; try { // load it Assembly ass = null; //string args = Path.GetFileNameWithoutExtension(pluginname); ass = Assembly.Load(args); if (ass != null) { ObjType = ass.GetType(args + ".PlugIn"); // look for the plugin interface // OK Lets create the object as we have the Report Type if (ObjType != null) { // create an instance of the plugin IPlugin plug = (IPlugin)Activator.CreateInstance(ObjType); // create an entry for the plugin PluginEntry pe = new PluginEntry(plug, args); //add the entry to the list of plugins m_plugins.Add(pe); //mark the plugin as enabled by default pe.m_enabled = true; if (m_pluginstates.InList(args)) { // this plugin is listed in the disabled list. DebugLogger.Instance().LogInfo("Plugin " + args + " marked disabled"); pe.m_enabled = false; } //get the vendor id of the newly loaded plugin int vid = plug.GetInt("VendorID"); //look for the license key for this plugin LicenseKey lk = KeyRing.Instance().Find(vid); // if we found it, mark it as licensed if (lk != null) { //initialize the plugin by setting the host. if (pe.m_enabled) { plug.Host = this; // this will initialize the plugin - the plugin's init function will be called DebugLogger.Instance().LogInfo("Loaded licensed plugin " + args); } } /* * if (pe.m_enabled && pe.m_licensed) * { * DebugLogger.Instance().LogInfo("Loaded licensed plugin " + args); * }else if (pe.m_enabled && ) * */ DebugLogger.Instance().LogInfo("Loaded plugin " + args); } } } catch (Exception ex) { DebugLogger.Instance().LogError(ex.Message); } } } }
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; }
/// <summary> /// Gets the instance to the File Logger, creates if necessary /// </summary> /// <returns>Instance of this object</returns> public static DebugLogger Instance() { if (_instance == null) _instance = new DebugLogger(); return _instance; }
void SliceEv(Slicer.eSliceEvent ev, int layer, int totallayers) { String path = ""; switch (ev) { case Slicer.eSliceEvent.eSliceStarted: // if we're exporting images if (m_buildparms.exportimages) { // get the model name String modelname = m_obj.m_fullname; // strip off the file extension path = Path.GetDirectoryName(modelname); path += UVDLPApp.m_pathsep; path += Path.GetFileNameWithoutExtension(modelname); // strip off the file extension if (!Directory.Exists(path)) // check and see if a directory of that name exists, { Directory.CreateDirectory(path); // if not, create it } } break; case Slicer.eSliceEvent.eLayerSliced: //save the rendered image slice //render the slice if (m_buildparms.exportimages) { // get the model name String modelname = m_obj.m_fullname; // strip off the file extension path = Path.GetDirectoryName(modelname); path += UVDLPApp.m_pathsep; path += Path.GetFileNameWithoutExtension(modelname); // strip off the file extension Bitmap bmp = null; String imagename = path + m_pathsep + Path.GetFileNameWithoutExtension(modelname) + String.Format("{0:0000}", layer) + ".png"; bmp = UVDLPApp.Instance().m_slicefile.RenderSlice(layer); bmp.Save(imagename); } break; case Slicer.eSliceEvent.eSliceCompleted: m_gcode = GCodeGenerator.Generate(m_slicefile, m_printerinfo); /* * //get the path of the current object file * path = Path.GetDirectoryName(m_obj.m_fullname); * string fn = Path.GetFileNameWithoutExtension(m_obj.m_fullname); * if (!UVDLPApp.Instance().m_gcode.Save(path + UVDLPApp.m_pathsep + fn + ".gcode")) * { * DebugLogger.Instance().LogRecord("Cannot save GCode File " + path + m_pathsep + fn + ".gcode"); * } * */ SaveGCode(); break; case Slicer.eSliceEvent.eSliceCancelled: DebugLogger.Instance().LogRecord("Slicing Cancelled"); break; } }
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; } }
public void SetupDriver() { DebugLogger.Instance().LogRecord("Changing driver type to " + m_printerinfo.m_driverconfig.m_drivertype.ToString()); m_deviceinterface.Driver = DriverFactory.Create(m_printerinfo.m_driverconfig.m_drivertype); }