//good to go
        private void Square2Circle()
        {
            //center the square on the origin
            int full = m_net.Size - 1;
            int half = m_net.Size/2;

            //constrain verticle and horizontal lines
            Point2D N = new Point2D(0, 1);
            Point2D S = new Point2D(0, -1);
            Point2D E = new Point2D(1, 0);
            Point2D W = new Point2D(-1, 0);
            m_net.AlignEdge(m_net[half, full], m_net[half, 0], new AlignToSeg(N, S));
            m_net.AlignEdge(m_net[full, half], m_net[0, half], new AlignToSeg(E, W));

            //constrain diagonals
            Point2D NE = new Point2D(Math.Sqrt(0.5), Math.Sqrt(0.5));
            Point2D NW = new Point2D(Math.Sqrt(0.5), -Math.Sqrt(0.5));
            Point2D SE = new Point2D(-Math.Sqrt(0.5), Math.Sqrt(0.5));
            Point2D SW = new Point2D(-Math.Sqrt(0.5), -Math.Sqrt(0.5));
            m_net.AlignEdge(m_net[full, full], m_net[0, 0], new AlignToSeg(NE, SW));
            m_net.AlignEdge(m_net[full, 0], m_net[0, full], new AlignToSeg(NW, SE));

            //constrain specific points
            m_net[0, 0].Alignment = new AlignFixed(SW);
            m_net[full, full].Alignment = new AlignFixed(NE);
            m_net[full, 0].Alignment = new AlignFixed(NW);
            m_net[0, full].Alignment = new AlignFixed(SE);
            m_net[0, half].Alignment = new AlignFixed(W);
            m_net[half, 0].Alignment = new AlignFixed(S);
            m_net[full, half].Alignment = new AlignFixed(E);
            m_net[half, full].Alignment = new AlignFixed(N);
            m_net[half, half].Alignment = new AlignFixed(Point2D.Origin);

            //constrain to circle
            AlignToArc circle = new AlignToArc(Point2D.Origin, 1.0);
            m_net.AlignEdge(m_net[0, 0], m_net[full, 0], circle);
            m_net.AlignEdge(m_net[full, 0], m_net[full, full], circle);
            m_net.AlignEdge(m_net[full, full], m_net[0, full], circle);
            m_net.AlignEdge(m_net[0, full], m_net[0, 0], circle);

            //setup initial position if first time
            if (m_bFirstPass)
            {
                for (int i = 0; i < m_net.Size; i++)
                {
                    for (int j = 0; j < m_net.Size; j++)
                    {
                        if (m_net[i, j] != null)
                        {
                            m_net[i, j].Position *= 2.0 / (double)full;
                            m_net[i, j].Position -= new Point2D(1.0, 1.0);
                        }
                    }
                }
            }
        }
        //will do in a pinch
        private void Square2Heart()
        {
            Point2D
                A = new Point2D(-2.0, 0),
                B = new Point2D(-1.0, 0),
                C = new Point2D(0, 0),
                D = new Point2D(1.0, 0),
                E = new Point2D(2.0, 0),
                F = new Point2D(-Math.Sqrt(2.0), -Math.Sqrt(2.0)),
                G = new Point2D(Math.Sqrt(2.0), -Math.Sqrt(2.0)),
                H = new Point2D(0, -2.0 * Math.Sqrt(2));

            Aligner HtoF = new AlignToSeg(H, F);
            Aligner HtoG = new AlignToSeg(H, G);
            Aligner FtoA = new AlignToArc(C, 2.0, A, F);
            Aligner EtoG = new AlignToArc(C, 2.0, G, E);
            Aligner AtoC = new AlignToArc(B, 1.0, C, A);
            Aligner CtoE = new AlignToArc(D, 1.0, E, C);

            AlignCombo Left = new AlignCombo();
            Left.AddAligner(HtoF);
            Left.AddAligner(FtoA);
            Left.AddAligner(AtoC);

            AlignCombo Right = new AlignCombo();
            Right.AddAligner(HtoG);
            Right.AddAligner(EtoG);
            Right.AddAligner(CtoE);

            m_net.AlignEdge(m_net[0, 0], m_net[m_net.Size - 1, m_net.Size - 1], new AlignToSeg(H, C));
            m_net.AlignEdge(m_net[0, 0], m_net[0, m_net.Size - 1], Left);
            m_net.AlignEdge(m_net[0, 0], m_net[m_net.Size - 1, 0], Right);

            int quarter = m_net.Size / 4;
            m_net.AlignEdge(m_net[0, m_net.Size - 1], m_net[quarter, m_net.Size - 1], Left);
            m_net.AlignEdge(m_net[m_net.Size - 1, 0], m_net[m_net.Size - 1, quarter], Right);
            for (int i = quarter; i < m_net.Size; i++)
            {
                double fraction = (double)(i - quarter) / (double)(m_net.Size - 1 - quarter);
                fraction *= Math.PI;
            #if false //fix top arc
                m_net[i, m_net.Size - 1].Alignment = new AlignFixed(new Point2D(-1.0 - Math.Cos(fraction), Math.Sin(fraction)));
                m_net[m_net.Size - 1, i].Alignment = new AlignFixed(new Point2D(1.0 + Math.Cos(fraction), Math.Sin(fraction)));
            #else //initialize position
                if (m_bFirstPass)
                {
                    m_net[i, m_net.Size - 1].Position = new Point2D(-1.0 - Math.Cos(fraction), Math.Sin(fraction));
                    m_net[m_net.Size - 1, i].Position = new Point2D(1.0 + Math.Cos(fraction), Math.Sin(fraction));
                }
            #endif
            }
            //fix points
            m_net[0, 0].Alignment = new AlignFixed(H);
            m_net[m_net.Size - 1, m_net.Size - 1].Alignment = new AlignFixed(C);
        }
        //good to go
        private void Hexagon2Circle()
        {
            int full = (m_net.Size - 1);
            int third = m_net.Size / 3;
            int twothirds = m_net.Size * 2 / 3;

            if (m_bFirstPass)
            {
                m_net = new TriangularNet(m_net.Size);
                for (int i = 0; i < m_net.Size; i++)
                {
                    for (int j = 0; j < m_net.Size; j++)
                    {
                        if (m_net[i, j] != null)
                        {
                            m_net[i, j].Position *= 3.0 / m_net.Size;
                            m_net[i, j].Position += new Point2D(-2.0, -1.0);
                        }
                    }
                }
            }

            //zero out what we don't need
            for (int i = 0; i < m_net.Size; i++)
            {
                for (int j = 0; j < m_net.Size; j++)
                {
                    if (m_net[i, j] != null)
                    {
                        if (i < j ||           // remove top half of triangle
                            i < third ||       // clip one corner
                            j > twothirds ||    // clip second corner
                            i > j + twothirds ) // clip third corner
                        {
                            m_net[i, j] = null;
                        }
                    }
                }
            }

            m_net.SetNeighbors();

            //align arcs
            AlignToArc AlignToCircle = new AlignToArc(Point2D.Origin, 1.0);

            m_net.AlignEdge(m_net[twothirds, twothirds], m_net[full, twothirds], AlignToCircle);
            m_net.AlignEdge(m_net[full, twothirds], m_net[full, third], AlignToCircle);
            m_net.AlignEdge(m_net[full, third], m_net[twothirds, 0], AlignToCircle);
            m_net.AlignEdge(m_net[twothirds, 0], m_net[third, 0], AlignToCircle);
            m_net.AlignEdge(m_net[third, 0], m_net[third, third], AlignToCircle);
            m_net.AlignEdge(m_net[third, third], m_net[twothirds, twothirds], AlignToCircle);

            //Align Points
            m_net[full, third].Alignment = new AlignFixed( Point2D.FromPolar(1.0, 0.0 * Math.PI) );
            m_net[full, twothirds].Alignment = new AlignFixed( Point2D.FromPolar(1.0, (1.0/3.0) * Math.PI) );
            m_net[twothirds, twothirds].Alignment = new AlignFixed( Point2D.FromPolar(1.0, (2.0/3.0) * Math.PI) );
            m_net[third, third].Alignment = new AlignFixed( Point2D.FromPolar(1.0, Math.PI) );
            m_net[third, 0].Alignment = new AlignFixed( Point2D.FromPolar(1.0, (4.0/3.0) * Math.PI) );
            m_net[twothirds, 0].Alignment = new AlignFixed( Point2D.FromPolar(1.0, (5.0/3.0) * Math.PI) );
        }
        //good to go
        private void Diamond2Lens()
        {
            double Sqrt3 = Math.Sqrt(3.0);
            int full = (m_net.Size-1);
            int half = m_net.Size / 2;
            int left = (int)((double)m_net.Size * (Sqrt3 - 1.0) / (2.0 * Sqrt3)) + 1;
            int right = (int)((double)m_net.Size * (Sqrt3 + 1.0) / (2.0 * Sqrt3)) - 1;

            //zero out what we don't need
            for (int i = 0; i < m_net.Size; i++)
            {
                for (int j = 0; j < m_net.Size; j++)
                {
                    if (m_net[i, j] != null)
                    {
                        if ((double)i + (double)j / Sqrt3 < (double)full * 0.5 - DMS.EPSILON ||
                            (double)i + (double)j / Sqrt3 > (double)full * (0.5 + 1.0/Sqrt3) + DMS.EPSILON ||
                            (double)i - (double)j /Sqrt3 > (double)full * 0.5 + DMS.EPSILON ||
                            (double)i - (double)j / Sqrt3 < (double)full * (0.5 - 1.0/Sqrt3) - DMS.EPSILON)
                        {
                            m_net[i, j] = null;
                        }
                    }
                }
            }

            Point2D A = -Point2D.XAxis;
            Point2D B = new Point2D(0, 1.0 / Sqrt3);
            Point2D C = Point2D.XAxis;
            Point2D D = new Point2D(0, -1.0 / Sqrt3);
            Point2D E = Point2D.Origin;

            AlignToArc AlignTop = new AlignToArc(D, 2.0 / Sqrt3, C, A);
            AlignToArc AlignBottom = new AlignToArc(B, 2.0 / Sqrt3, A, C);

            m_net.SetNeighbors();

            //align arcs
            for (int i = 0; i < m_net.Size; i++)
            {
                for (int j = 0; j < m_net.Size; j++)
                {
                    if (m_net[i, j] != null)
                    {
                        if (m_net[i, j].North == null)
                            m_net[i, j].Alignment = AlignTop;
                        else if (m_net[i, j].South == null)
                            m_net[i, j].Alignment = AlignBottom;
                        else
                            m_net[i, j].Alignment = new Aligner(); //generic non-aligner
                    }
                }
            }

            //align horizontal, align vertical axes
            m_net.AlignEdge(m_net[half, 0], m_net[half, full], new AlignToSeg(B, D));
            m_net.AlignEdge(m_net[left, half], m_net[right, half], new AlignToSeg(A, C));

            //align points
            m_net[half, 0].Alignment = new AlignFixed(D);
            m_net[half, full].Alignment = new AlignFixed(B);
            m_net[left, half].Alignment = new AlignFixed(A);
            m_net[right, half].Alignment = new AlignFixed(C);
        }
        //good to go
        private void Bitmap2Circle()
        {
            Aligner circle = new AlignToArc(Point2D.Origin, 1.0);
            double full = m_net.Size - 1;
            for (int i = 0; i < m_net.Size; i++)
            {
                for (int j = 0; j < m_net.Size; j++)
                {
                    Point2D pt = new Point2D(i, j) / full;
                    if (m_mask.GetPixel(pt).ToArgb() == Color.Black.ToArgb())
                        m_net[i, j] = null;
                }
            }
            m_net.SetNeighbors();

            //calculate center, and determine which points are edges.
            Point2D center = new Point2D();

            bool[,] isedge = new bool[m_net.Size, m_net.Size];
            for (int i = 0; i < m_net.Size; i++)
            {
                for (int j = 0; j < m_net.Size; j++)
                {
                    isedge[i, j] = false;

                    if (m_net[i, j] == null)
                        continue;

                    if (m_net[i, j].East == null ||
                        m_net[i, j].West == null ||
                        m_net[i, j].South == null ||
                        m_net[i, j].North == null)
                    {
                        isedge[i, j] = true;
                    }

                    center += m_net[i, j].Position;
                }
            }
            center /= m_net.Count;

            //fix edge points to circle
            for (int i = 0; i < m_net.Size; i++)
            {
                for (int j = 0; j < m_net.Size; j++)
                {
                    if (m_net[i, j] == null)
                        continue;

                    if (isedge[i, j])
                        m_net[i, j].Alignment = circle;

                    if (m_bFirstPass)
                    {
                        m_net[i, j].Position -= center;
                        m_net[i, j].Position = m_net[i,j].Position / full;
                    }
                }
            }
        }
        private void XtoCircle()
        {
            int full = m_net.Size - 1;
            int half = m_net.Size / 2;
            int threequarters = m_net.Size / 4 * 3;
            int quarter = m_net.Size / 4;
            int third = m_net.Size / 3;
            int twothirds = m_net.Size / 3 * 2;
            int sixth = m_net.Size / 6;

            Indicatrix
                A = m_net[0, twothirds],
                B = m_net[third, twothirds],
                C = m_net[half, half],
                D = m_net[twothirds, twothirds],
                E = m_net[full, twothirds],
                F = m_net[twothirds, third],
                G = m_net[full, 0],
                H = m_net[twothirds, 0],
                I = m_net[half, sixth],
                J = m_net[third, 0],
                K = m_net[0, 0],
                L = m_net[third, third];

            AlignToArc TL = new AlignToArc(Point2D.Origin, 1.0, Point2D.YAxis, -Point2D.XAxis);
            AlignToArc BL = new AlignToArc(Point2D.Origin, 1.0, -Point2D.XAxis, -Point2D.YAxis);
            AlignToArc BR = new AlignToArc(Point2D.Origin, 1.0, -Point2D.YAxis, Point2D.XAxis);
            AlignToArc TR = new AlignToArc(Point2D.Origin, 1.0, Point2D.XAxis, Point2D.YAxis);

            m_net.AlignEdge(L, A, TL);
            m_net.AlignEdge(A, B, TL);
            m_net.AlignEdge(B, C, TL);
            m_net.AlignEdge(C, D, TR);
            m_net.AlignEdge(D, E, TR);
            m_net.AlignEdge(E, F, TR);
            m_net.AlignEdge(F, G, BR);
            m_net.AlignEdge(G, H, BR);
            m_net.AlignEdge(H, I, BR);
            m_net.AlignEdge(I, J, BL);
            m_net.AlignEdge(J, K, BL);
            m_net.AlignEdge(K, L, BL);

            m_net.AlignEdge(m_net[0, third], m_net[full, third], new AlignToSeg(-Point2D.XAxis, Point2D.XAxis));
            m_net.AlignEdge(m_net[half, 0], m_net[half, full], new AlignToSeg(-Point2D.YAxis, Point2D.YAxis));

            C.Alignment = new AlignFixed(Point2D.YAxis);
            F.Alignment = new AlignFixed(Point2D.XAxis);
            I.Alignment = new AlignFixed(-Point2D.YAxis);
            L.Alignment = new AlignFixed(-Point2D.XAxis);

            //now delete ones we don't need
            for (int i = 0; i < m_net.Size; i++)
            {
                for (int j = 0; j < m_net.Size; j++)
                {
                    if (j > twothirds)
                        m_net[i, j] = null;
                    if (Math.Abs(i + j - half - third) <= sixth)
                        continue;
                    if (i - j <= third && i - j >= 0)
                        continue;
                    m_net[i, j] = null;
                }
            }

            //now scale them for a good start
            if( m_bFirstPass)
                for (int i = 0; i < m_net.Size; i++)
                    for (int j = 0; j < m_net.Size; j++)
                        if (m_net[i, j] != null)
                            m_net[i, j].Position = m_net[i, j].Position * 2.0 / m_net.Size - new Point2D(1.0, 1.0);
        }
        //good to go
        private void Triangle2Rouleaux()
        {
            if (m_bFirstPass)
            {
                m_net = new TriangularNet(m_net.Size);
            }

            double Sqrt3 = Math.Sqrt(3.0);
            int full = (m_net.Size - 1);
            int half = m_net.Size / 2;

            //zero out what we don't need
            for (int i = 0; i < m_net.Size; i++)
            {
                for (int j = 0; j < m_net.Size; j++)
                {
                    if (m_net[i, j] != null)
                    {
                        if ( i < j )
                        {
                            m_net[i, j] = null;
                        }
                    }
                }
            }

            Point2D A = new Point2D(0, 1.0 / Math.Sqrt(2.0));
            Point2D B = new Point2D(-Sqrt3 / (2.0 * Math.Sqrt(2.0)), -1.0 / (2.0 * Math.Sqrt(2.0)) );
            Point2D C = new Point2D(Sqrt3 / (2.0 * Math.Sqrt(2.0)), -1.0 / (2.0 * Math.Sqrt(2.0)) );
            double radius = (A - B).R;

            AlignToArc AlignAB = new AlignToArc(C, radius, A, B);
            AlignToArc AlignBC = new AlignToArc(A, radius, B, C);
            AlignToArc AlignAC = new AlignToArc(B, radius, C, A);

            m_net.SetNeighbors();

            //align arcs
            m_net.AlignEdge(m_net[full, full], m_net[full, 0], AlignAC);
            m_net.AlignEdge(m_net[0, 0], m_net[full, full], AlignAB);
            m_net.AlignEdge(m_net[0, 0], m_net[full, 0], AlignBC);

            //align points
            m_net[0, 0].Alignment = new AlignFixed(B);
            m_net[full, full].Alignment = new AlignFixed(A);
            m_net[full, 0].Alignment = new AlignFixed(C);
        }