Ejemplo n.º 1
0
        public bool CheckZoom(Point point, out Ellipse ellipse, out double angle)
        {
            stroke[curIndex] = point;
            if (strokeLength < MAX_CAPACITY) strokeLength++;

            angle = 0;
            ellipse = new Ellipse();

            var curDir = new Point(point.X - stroke[prevIndex].X, point.Y - stroke[prevIndex].Y);

            int cnt = 0;
            int index = 0;
            for (int i = 2; i < strokeLength; i++)
            {
                var index1 = (curIndex + MAX_CAPACITY - i) % MAX_CAPACITY;
                var index2 = (curIndex + MAX_CAPACITY - i + 1) % MAX_CAPACITY;
                var x = stroke[index2].X - stroke[index1].X;
                var y = stroke[index2].Y - stroke[index1].Y;

                if (x * x + y * y < MIN_SQDIR) break;

                var dot = x * curDir.X + y * curDir.Y;

                if ((cnt % 2 == 0 ? dot : -dot) < 0)
                {
                    cnt++;
                    if (cnt >= 2)
                    {
                        index = index1;
                        break;
                    }
                }
            }

            bool ans = false;

            if (cnt >= 2)
            {
                ellipse = GetEllipse(index, curIndex);
                // ellise.Eが小さいほどまん丸に近い
                if (ellipse.E < 0.9)
                {
                    // ズーム
                    double x1 = stroke[prevIndex].X - ellipse.X;
                    double y1 = stroke[prevIndex].Y - ellipse.Y;
                    double x2 = point.X - ellipse.X;
                    double y2 = point.Y - ellipse.Y;

                    double dot = x1 * x2 + y1 * y2;
                    double d = Math.Sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2));

                    angle = Math.Acos(dot / d) * (x1 * y2 - x2 * y1 > 0 ? 1 : -1);
                    ans = true;
                }
            }

            curIndex = (curIndex + 1) % MAX_CAPACITY;
            prevIndex = (curIndex + MAX_CAPACITY - 1) % MAX_CAPACITY;

            return ans;
        }
Ejemplo n.º 2
0
        Ellipse GetEllipse(int start, int end)
        {
            for (int i = 0; i < m.Length; i++) m[i] = l[i] = u[i] = 0;
            for (int i = 0; i < v.Length; i++) v[i] = y[i] = a[i] = 0;

            for (int i = start; i != end; i = (i + 1) % MAX_CAPACITY)
            {
                double px = stroke[i].X;
                double py = stroke[i].Y;
                double px2 = px * px;
                double py2 = py * py;
                double px3 = px2 * px;
                double py3 = py2 * py;
                double py4 = py2 * py2;

                m[0] += px2 * py2;  m[1] += px * py3;   m[2] += px2 * py;   m[3] += px * py2;   m[4] += px * py;
                m[5] += px * py3;   m[6] += py4;        m[7] += px * py2;   m[8] += py3;        m[9] += py2;
                m[10] += px2 * py;  m[11] += px * py2;  m[12] += px2;       m[13] += px * py;   m[14] += px;
                m[15] += px * py2;  m[16] += py3;       m[17] += px * py;   m[18] += py2;       m[19] += py;
                m[20] += px * py;   m[21] += py2;       m[22] += px;        m[23] += py;        m[24] += 1;

                v[0] -= px3 * py;
                v[1] -= px2 * py2;
                v[2] -= px3;
                v[3] -= px2 * py;
                v[4] -= px2;
            }

            // LU分解
            LU(m, l, u);

            // Ly = v の y を求める
            for (int i = 0; i < 5; i++)
            {
                double s = 0.0;
                for (int j = 0; j < i; j++) s += l[i * N + j] * y[j];
                y[i] = (v[i] - s) / l[i * N + i];
            }
            // Ua = y の a を求める
            for (int i = 4; i >= 0; i--)
            {
                double s = 0.0;
                for (int j = 4; j > i; j--) s += u[i * N + j] * a[j];
                a[i] = (y[i] - s) / u[i * N + i];
            }

            double x0 = (a[0] * a[3] - 2 * a[1] * a[2]) / (4 * a[1] - a[0] * a[0]);
            double y0 = (a[0] * a[2] - 2 * a[3]) / (4 * a[1] - a[0] * a[0]);
            double theta = Math.Atan(a[0] / (1.0 - a[1])) / 2.0;
            double sin = Math.Sin(theta), cos = Math.Cos(theta);
            double r1 = Math.Sqrt(
                (x0 * cos + y0 * sin) * (x0 * cos + y0 * sin) -
                a[4] * cos * cos -
                ((x0 * sin - y0 * cos) * (x0 * sin - y0 * cos) - a[4] * sin * sin) * (sin * sin - a[1] * cos * cos) / (cos * cos - a[1] * sin * sin)
            );
            double r2 = Math.Sqrt(
                (x0 * sin - y0 * cos) * (x0 * sin - y0 * cos) -
                a[4] * sin * sin -
                ((x0 * cos + y0 * sin) * (x0 * cos + y0 * sin) - a[4] * cos * cos) * (cos * cos - a[1] * sin * sin) / (sin * sin - a[1] * cos * cos)
            );

            double maxR = Math.Max(r1, r2);
            double minR = Math.Min(r1, r2);
            double e = Math.Sqrt(Math.Abs(maxR * maxR - minR * minR) / (maxR * maxR));
            var ellipse = new Ellipse(x0, y0, theta, maxR, minR, e);
            return ellipse;
        }