private void SelectVertexByRect()
        {
            Vector2d        minV      = Vector2d.Min(mouseDownPosition, currMousePosition);
            Vector2d        size      = Vector2d.Max(mouseDownPosition, currMousePosition) - minV;
            Rectangle       rect      = new Rectangle((int)minV.x, (int)minV.y, (int)size.x, (int)size.y);
            Rectangle       viewport  = new Rectangle(0, 0, this.Width, this.Height);
            OpenGLProjector projector = new OpenGLProjector();
            Mesh            m         = currMeshRecord.Mesh;
            bool            laser     = Program.toolsProperty.Laser;
            double          eps       = Program.toolsProperty.DepthTolerance;

            if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
            {
                for (int i = 0, j = 0; i < m.VertexCount; i++, j += 3)
                {
                    Vector3d v = projector.Project(m.VertexPos, j);
                    if (viewport.Contains((int)v.x, (int)v.y))
                    {
                        bool flag = rect.Contains((int)v.x, (int)v.y);
                        flag &= (laser || projector.GetDepthValue((int)v.x, (int)v.y) - v.z >= eps);
                        if (flag)
                        {
                            m.Flag[i] = (byte)1;
                        }
                    }
                }
            }

            else if ((Control.ModifierKeys & Keys.Control) == Keys.Control)
            {
                for (int i = 0, j = 0; i < m.VertexCount; i++, j += 3)
                {
                    Vector3d v = projector.Project(m.VertexPos, j);
                    if (viewport.Contains((int)v.x, (int)v.y))
                    {
                        bool flag = rect.Contains((int)v.x, (int)v.y);
                        flag &= (laser || projector.GetDepthValue((int)v.x, (int)v.y) - v.z >= eps);
                        if (flag)
                        {
                            m.Flag[i] = (byte)0;
                        }
                    }
                }
            }

            else
            {
                for (int i = 0, j = 0; i < m.VertexCount; i++, j += 3)
                {
                    Vector3d v = projector.Project(m.VertexPos, j);
                    if (viewport.Contains((int)v.x, (int)v.y))
                    {
                        bool flag = rect.Contains((int)v.x, (int)v.y);
                        flag     &= (laser || projector.GetDepthValue((int)v.x, (int)v.y) - v.z >= eps);
                        m.Flag[i] = (byte)((flag) ? 1 : 0);
                    }
                }
            }
        }
        private void SelectVertexByPoint()
        {
            Rectangle       viewport  = new Rectangle(0, 0, this.Width, this.Height);
            OpenGLProjector projector = new OpenGLProjector();
            Mesh            m         = currMeshRecord.Mesh;
            bool            laser     = Program.toolsProperty.Laser;
            double          eps       = Program.toolsProperty.DepthTolerance;

            double minDis   = double.MaxValue;
            int    minIndex = -1;

            for (int i = 0, j = 0; i < m.VertexCount; i++, j += 3)
            {
                Vector3d v = projector.Project(m.VertexPos, j);
                Vector2d u = new Vector2d(v.x, v.y);
                if (!viewport.Contains((int)v.x, (int)v.y))
                {
                    continue;
                }
                if (!laser && projector.GetDepthValue((int)v.x, (int)v.y) - v.z < eps)
                {
                    continue;
                }

                double dis = (u - currMousePosition).Length();
                if (dis < minDis)
                {
                    minIndex = i;
                    minDis   = dis;
                }
            }
            if (minIndex == -1)
            {
                return;
            }
            //FormMain.CurrForm.OutputText("selected vertex: " + minIndex.ToString());

            if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
            {
                m.Flag[minIndex] = (byte)1;
            }
            else if ((Control.ModifierKeys & Keys.Control) == Keys.Control)
            {
                m.Flag[minIndex] = (byte)0;
            }
            else
            {
                for (int i = 0; i < m.VertexCount; i++)
                {
                    m.Flag[i] = (byte)0;
                }
                m.Flag[minIndex] = (byte)1;
            }
        }
        private bool StartMoving()
        {
            // find closest selected vertex
            this.GrabContext();
            OpenGLProjector projector = new OpenGLProjector();
            Mesh            m         = currMeshRecord.Mesh;
            Deformer        deformer  = currMeshRecord.Deformer;
            Rectangle       viewport  = new Rectangle(0, 0, this.Width, this.Height);
            double          eps       = Program.toolsProperty.DepthTolerance;
            double          minDis    = double.MaxValue;
            int             minIndex  = -1;

            for (int i = 0, j = 0; i < m.VertexCount; i++, j += 3)
            {
                if (m.Flag[i] == 0)
                {
                    continue;
                }
                Vector3d v3d = projector.Project(m.VertexPos, j);
                Vector2d v   = new Vector2d(v3d.x, v3d.y);
                if (viewport.Contains((int)v.x, (int)v.y) == false)
                {
                    continue;
                }
                if (projector.GetDepthValue((int)v.x, (int)v.y) - v3d.z < eps)
                {
                    continue;
                }

                double dis = (v - mouseDownPosition).Length();
                if (dis < minDis)
                {
                    minDis   = dis;
                    minIndex = i;
                }
            }
            if (minIndex == -1)
            {
                this.handleFlag = -1;
                this.handleIndex.Clear();
                this.oldHandlePos.Clear();
                return(false);
            }

            // find boundary box
            int flag = m.Flag[minIndex];

            this.handleFlag = flag;
            this.handleIndex.Clear();
            this.oldHandlePos.Clear();

            Vector3d c     = new Vector3d(0, 0, 0);
            int      count = 0;

            {
                for (int i = 0; i < m.VertexCount; i++)
                {
                    if (m.Flag[i] == flag)
                    {
                        Vector3d p = new Vector3d(m.VertexPos, i * 3);
                        c += p;
                        this.handleIndex.Add(i);
                        this.oldHandlePos.Add(p);
                        count++;
                    }
                }
            }
            c /= (double)count;

            this.handleCenter    = new Vector4d(c, 0);
            this.projectedCenter = projector.Project(handleCenter.x, handleCenter.y, handleCenter.z);
            return(true);
        }