Exemple #1
0
        /*
         * This function calculates the min and max x/y coordinates of this slice
         */
        public static MinMax_XY CalcMinMax_XY(List <Line2d> lines2d)
        {
            Line2d    l1 = (Line2d)lines2d[0];
            MinMax_XY mm = new MinMax_XY();

            //start the min / max off with some valid values
            //mm.xmin = mm.xmax = l1.p1.x;
            //mm.ymin = mm.ymax = l1.p1.y;
            mm.xmin = lines2d.Select(a => a.p1.x).Min();
            mm.xmax = lines2d.Select(a => a.p1.x).Max();
            mm.ymin = lines2d.Select(a => a.p1.y).Min();
            mm.ymax = lines2d.Select(a => a.p1.y).Max();
            //foreach (Line2d ln in lines2d)
            //{
            //    if (ln.p1.x < mm.xmin) mm.xmin = ln.p1.x;
            //    if (ln.p2.x < mm.xmin) mm.xmin = ln.p2.x;
            //    if (ln.p1.x > mm.xmax) mm.xmax = ln.p1.x;
            //    if (ln.p2.x > mm.xmax) mm.xmax = ln.p2.x;

            //    if (ln.p1.y < mm.ymin) mm.ymin = ln.p1.y;
            //    if (ln.p2.y < mm.ymin) mm.ymin = ln.p2.y;
            //    if (ln.p1.y > mm.ymax) mm.ymax = ln.p1.y;
            //    if (ln.p2.y > mm.ymax) mm.ymax = ln.p2.y;
            //}
            return(mm);
        }
Exemple #2
0
        public Bitmap RenderSlice(SliceBuildConfig sp)
        {
            // create a new bitmap that will be used to draw into
            Bitmap   bmp   = new Bitmap(sp.xres, sp.yres);
            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
            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++)
            {
                //      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 = p1.x + sp.XOffset;
                        pnt1.Y = p1.y + sp.YOffset;
                        pnt2.X = p2.x + sp.XOffset;
                        pnt2.Y = p2.y + sp.YOffset;
                        graph.DrawLine(pen, pnt1, pnt2);
                    }
                }
                else  // flag error
                {
                    DebugLogger.Instance().LogRecord("Row y=" + y + " odd # of points = " + points.Count);
                }
            }

            return(bmp);
        }
Exemple #3
0
        /*
         * This function calculates the min and max x/y coordinates of this slice
         */
        public static MinMax_XY CalcMinMax_XY(List <Line2d> lines2d)
        {
            Line2d    l1 = (Line2d)lines2d[0];
            MinMax_XY mm = new MinMax_XY();

            //start the min / max off with some valid values
            mm.xmin = mm.xmax = l1.p1.x;
            mm.ymin = mm.ymax = l1.p1.y;

            foreach (Line2d ln in lines2d)
            {
                if (ln.p1.x < mm.xmin)
                {
                    mm.xmin = ln.p1.x;
                }
                if (ln.p2.x < mm.xmin)
                {
                    mm.xmin = ln.p2.x;
                }
                if (ln.p1.x > mm.xmax)
                {
                    mm.xmax = ln.p1.x;
                }
                if (ln.p2.x > mm.xmax)
                {
                    mm.xmax = ln.p2.x;
                }

                if (ln.p1.y < mm.ymin)
                {
                    mm.ymin = ln.p1.y;
                }
                if (ln.p2.y < mm.ymin)
                {
                    mm.ymin = ln.p2.y;
                }
                if (ln.p1.y > mm.ymax)
                {
                    mm.ymax = ln.p1.y;
                }
                if (ln.p2.y > mm.ymax)
                {
                    mm.ymax = ln.p2.y;
                }
            }
            return(mm);
        }
Exemple #4
0
        /// <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
        }
        /*
         This function calculates the min and max x/y coordinates of this slice
         */
        public MinMax_XY CalcMinMax_XY(ArrayList lines2d)
        {
            Line2d l1 = (Line2d)lines2d[0];
            MinMax_XY mm = new MinMax_XY();
            //start the min / max off with some valid values
            mm.xmin = mm.xmax = l1.p1.x;
            mm.ymin = mm.ymax = l1.p1.y;

            foreach (Line2d ln in lines2d)
            {
                if (ln.p1.x < mm.xmin) mm.xmin = ln.p1.x;
                if (ln.p2.x < mm.xmin) mm.xmin = ln.p2.x;
                if (ln.p1.x > mm.xmax) mm.xmax = ln.p1.x;
                if (ln.p2.x > mm.xmax) mm.xmax = ln.p2.x;

                if (ln.p1.y < mm.ymin) mm.ymin = ln.p1.y;
                if (ln.p2.y < mm.ymin) mm.ymin = ln.p2.y;
                if (ln.p1.y > mm.ymax) mm.ymax = ln.p1.y;
                if (ln.p2.y > mm.ymax) mm.ymax = ln.p2.y;
            }
            return mm;
        }
Exemple #6
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, 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);
            }
        }
Exemple #7
0
        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>
        /// 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;
        }
Exemple #9
0
        /// <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);
            }
        }