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);
                    }
        }
        //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 Square2Parallelogram()
        {
            Point2D posA = new Point2D(0, 0);
            Point2D posB = new Point2D(1, 0);
            Point2D posC = new Point2D(1, 1);
            Point2D posD = new Point2D(2, 1);

            int full = m_net.Size - 1;

            AlignToSeg AB = new AlignToSeg(posA, posB);
            AlignToSeg BD = new AlignToSeg(posB, posD);
            AlignToSeg CD = new AlignToSeg(posC, posD);
            AlignToSeg AC = new AlignToSeg(posA, posC);

            //edges
            m_net.AlignEdge(m_net[0, 0], m_net[0, full], AC);
            m_net.AlignEdge(m_net[0, full], m_net[full, full], CD);
            m_net.AlignEdge(m_net[full, full], m_net[full, 0], BD);
            m_net.AlignEdge(m_net[full, 0], m_net[0, 0], AB);

            //vertices
            m_net[0, 0].Alignment = new AlignFixed(posA);
            m_net[0, full].Alignment = new AlignFixed(posC);
            m_net[full, full].Alignment = new AlignFixed(posD);
            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 - posD/2.0;
                    }
        }
        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
        }