private void Square2Triangle()
        {
            Point2D posA = new Point2D(-1.0, 0);
            Point2D posB = new Point2D(1.0, 0);
            Point2D posC = new Point2D(0, Math.Sqrt(3));

            int half = m_net.Size / 2;
            int full = m_net.Size - 1;

            AlignToSeg AC = new AlignToSeg(posA, posC);
            AlignToSeg OB = new AlignToSeg(Point2D.Origin, posB);
            AlignToSeg AO = new AlignToSeg(posA, Point2D.Origin);
            AlignToSeg BC = new AlignToSeg(posB, posC);
            AlignToSeg CO = new AlignToSeg(posC, Point2D.Origin);

            AlignCombo Left = new AlignCombo();
            Left.AddAligner(AC);
            Left.AddAligner(AO);
            AlignCombo Right = new AlignCombo();
            Right.AddAligner(BC);
            Right.AddAligner(OB);

            //edges
            m_net.AlignEdge(m_net[0, 0], m_net[0, full], Left);
            m_net.AlignEdge(m_net[0, full], m_net[half, full], Left);
            m_net.AlignEdge(m_net[half, 0], m_net[0, 0], Left);

            m_net.AlignEdge(m_net[half, full], m_net[full, full], Right);
            m_net.AlignEdge(m_net[full, full], m_net[full, 0], Right);
            m_net.AlignEdge(m_net[half, 0], m_net[full, 0], Right);

            //centerline
            m_net.AlignEdge(m_net[half, 0], m_net[half, full], CO);

            m_net[half, 0].Alignment = new AlignFixed(Point2D.Origin);
            m_net[half, full].Alignment = new AlignFixed(posC);
            m_net[0, 0].Alignment = new AlignFixed(posA);
            m_net[full, 0].Alignment = new AlignFixed(posB);

            //precondition the points:
            if( m_bFirstPass)
                for (int i = 0; i < m_net.Size; i++)
                    for (int j = 0; j < m_net.Size; j++)
                    {
                        m_net[i, j].Position = m_net[i, j].Position * 2.0 / (double)m_net.Size + new Point2D(-1.0, 0);
                    }
        }
        // good to go
        private void Square2Rectangle()
        {
            Point2D BL = new Point2D(0.0, 0.0);
            Point2D BR = new Point2D(1.0, 0.0);
            Point2D TR = new Point2D(1.0, m_Ratio);
            Point2D TL = new Point2D(0.0, m_Ratio);
            int full = m_net.Size - 1;

            //create aligner
            AlignCombo rectangle = new AlignCombo();
            rectangle.AddAligner(new AlignToSeg(TL, TR));
            rectangle.AddAligner(new AlignToSeg(BL, BR));
            rectangle.AddAligner(new AlignToSeg(TL, BL));
            rectangle.AddAligner(new AlignToSeg(BR, TR));

            //constrain the sides
            for (int i = 0; i < m_net.Size; i++)
            {
                m_net[i, full].Alignment = rectangle; //top
                m_net[i, 0].Alignment = rectangle; //bottom
                m_net[full, i].Alignment = rectangle; //right
                m_net[0, i].Alignment = rectangle; //left
            }

            //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++)
                    {
                        m_net[i, j].Position /= (double)full;
                        m_net[i, j].Position.Y *= m_Ratio;
                    }
                }
            }
        }
        // good to go
        private void Square2Oval()
        {
            Indicatrix
                TL = m_net[0, m_net.Size - 1],
                BL = m_net[0, 0],
                TR = m_net[m_net.Size - 1, m_net.Size - 1],
                BR = m_net[m_net.Size - 1, 0];
            Point2D
                posTL = new Point2D(-1, 1),
                posTR = new Point2D(1, 1),
                posBL = new Point2D(-1, -1),
                posBR = new Point2D(1, -1),
                center;

            double radius = Math.Sqrt(2);

            //adjust 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++)
                        m_net[i, j].Position = m_net[i, j].Position - new Point2D(m_net.Size/2, m_net.Size/2);

            AlignCombo perimeter = new AlignCombo();

            center = new Point2D(0, 1); //typically Point2D.Origin;
            radius = (center - posTL).R;
            perimeter.AddAligner(new AlignToArc(center, radius, posTR, posTL));
            center = new Point2D(0, -1); //typically Point2D.Origin;
            radius = (center - posBL).R;
            perimeter.AddAligner(new AlignToArc(center, radius, posBL, posBR));
            perimeter.AddAligner(new AlignToSeg(posTL, posBL));
            perimeter.AddAligner(new AlignToSeg(posTR, posBR));

            m_net.AlignEdge(TL, TR, perimeter);
            m_net.AlignEdge(BL, BR, perimeter);
            m_net.AlignEdge(TL, BL, perimeter);
            m_net.AlignEdge(TR, BR, perimeter);
        }
        //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);
        }
        private void Parallelogram2Square()
        {
            int full = m_net.Size - 1;
            int half = m_net.Size / 2;

            //remove points outside parallelogram
            for (int i = 0; i < m_net.Size; i++)
            {
                for (int j = 0; j < m_net.Size; j++)
                {
                    if (j > half)
                        m_net[i, j] = null;
                    else if (i + j < half)
                        m_net[i, j] = null;
                    else if (i + j > full)
                        m_net[i, j] = null;
                }

            }

            Point2D posA = new Point2D(-1, -1);
            Point2D posB = new Point2D(1, -1);
            Point2D posC = new Point2D(-1, 1);
            Point2D posD = new Point2D(1, 1);
            Indicatrix indA = m_net[half,0];
            Indicatrix indB = m_net[full,0];
            Indicatrix indC = m_net[0,half];
            Indicatrix indD = m_net[half,half];
            #if true //free floating
            AlignToSeg AB = new AlignToSeg(posA, posB);
            AlignToSeg BD = new AlignToSeg(posB, posD);
            AlignToSeg CD = new AlignToSeg(posC, posD);
            AlignToSeg AC = new AlignToSeg(posA, posC);
            AlignCombo BAC = new AlignCombo(); BAC.AddAligner(AB); BAC.AddAligner(AC);
            AlignCombo BDC = new AlignCombo(); BDC.AddAligner(BD); BDC.AddAligner(CD);
            AlignCombo ABCD = new AlignCombo(); ABCD.AddAligner(AB); ABCD.AddAligner(BD); ABCD.AddAligner(CD); ABCD.AddAligner(AC);

            //edges
            m_net.AlignEdge(indA, indC, ABCD); //AC
            m_net.AlignEdge(indC, indD, ABCD); //CD
            m_net.AlignEdge(indD, indB, ABCD); //DB
            m_net.AlignEdge(indB, indA, ABCD); //BA

            //vertices
            indA.Alignment = new AlignFixed(posA);
            //indB.Alignment = new AlignFixed(posB);
            //indC.Alignment = new AlignFixed(posC);
            indD.Alignment = new AlignFixed(posD);

            //precondition the points:
            if (m_bFirstPass)
            {
                for (int i = 0; i < m_net.Size; i++)
                {
                    for (int j = 0; j < m_net.Size; j++)
                    {
                        double x = (double)i / half - 1.0;
                        double y = (double)j / half;
                        x += y;
                        x *= 2.0; x -= 1.0;
                        y *= 2.0; y -= 1.0;
                        if (m_net[i, j] != null)
                            m_net[i, j].Position = new Point2D(x, y);
                    }
                }
            }
            #else //fixed
            double perimeter = (double)half * 2.0 * (1.0 + Math.Sqrt(2.0));
            for (int i = 0; i <= half; i++)
            {
                for( int j=0; j<4; j++)
                {
                    double dist = 0.0;
                    Indicatrix element = null;
                    switch( j )
                    {
                        case 0:
                            //A-B, m_net[half,0] .. m_net[full,0]
                            dist = (double)i;
                            element = m_net[half+i,0];
                            break;
                        case 1:
                            //B-D, m_net[full,0] ..m_net[half,half]
                            dist = (double)half + Math.Sqrt(2.0) * (double)i;
                            element = m_net[full-i,i];
                            break;
                        case 2:
                            //D-C, m_net[half, half] .. m_net[0, half]
                            dist = (double)half * (1.0 + Math.Sqrt(2.0)) + (double)i;
                            element = m_net[half-i, half];
                            break;
                        case 3:
                            //C-A, m_net[0, half] .. m_net[half, 0]
                            dist = (double)half * (2.0 + Math.Sqrt(2.0)) + Math.Sqrt(2.0) * (double)i;
                            element = m_net[i, half-i];
                            break;
                    }

                    //dist should be 0..half*(2+2sqrt2)
                    dist /= (double)half;
                    //dist should be 0..2+2sqrt2
                    dist -= 1.0;
                    //dist should be -1..1+2sqrt2
                    if (dist < 0.0) dist += (2.0 + 2.0 * Math.Sqrt(2.0));
                    //dist should be 0..2+2sqrt2
                    dist /= (2.0 + 2.0 * Math.Sqrt(2.0));
                    //dist should be 0..1
                    dist *= 4.0;
                    //dist should be 0..4

                    int integerpart = (int)dist;
                    double fractionalpart = dist - integerpart;
                    switch (integerpart)
                    {
                        case 0:
                            element.Alignment = new AlignFixed( posA + (posB-posA) * fractionalpart);
                            break;
                        case 1:
                            element.Alignment = new AlignFixed( posB + (posD-posB) * fractionalpart);
                            break;
                        case 2:
                            element.Alignment = new AlignFixed( posD + (posC-posD) * fractionalpart);
                            break;
                        case 3:
                            element.Alignment = new AlignFixed( posC + (posA-posC) * fractionalpart);
                            break;
                        default:
                            element.Alignment = new AlignFixed(posA);
                            break;
                    }
                }
            }
            #endif
        }
        //good to go
        private void Bitmap2Rectangle()
        {
            Bitmap2Circle();

            //create new aligner
            Point2D
                TL = new Point2D(-m_Ratio, 1),
                TR = new Point2D(m_Ratio, 1),
                BL = new Point2D(-m_Ratio, -1),
                BR = new Point2D(m_Ratio, -1);
            AlignCombo ToRectangle = new AlignCombo();
            ToRectangle.AddAligner(new AlignToSeg(TR, TL));
            ToRectangle.AddAligner(new AlignToSeg(BL, TL));
            ToRectangle.AddAligner(new AlignToSeg(BL, BR));
            ToRectangle.AddAligner(new AlignToSeg(TR, BR));

            //set alignment
            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 (m_net[i, j].Alignment is AlignToArc)
                    {
                        m_net[i, j].Alignment = ToRectangle;
                    }
                }
            }
        }