Blame mono/Diagram/Geometry.cs

Ivan Mahonin 8cb222
/*
Ivan Mahonin 8cb222
    ......... 2015 Ivan Mahonin
Ivan Mahonin 8cb222
Ivan Mahonin 8cb222
    This program is free software: you can redistribute it and/or modify
Ivan Mahonin 8cb222
    it under the terms of the GNU General Public License as published by
Ivan Mahonin 8cb222
    the Free Software Foundation, either version 3 of the License, or
Ivan Mahonin 8cb222
    (at your option) any later version.
Ivan Mahonin 8cb222
Ivan Mahonin 8cb222
    This program is distributed in the hope that it will be useful,
Ivan Mahonin 8cb222
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Ivan Mahonin 8cb222
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Ivan Mahonin 8cb222
    GNU General Public License for more details.
Ivan Mahonin 8cb222
Ivan Mahonin 8cb222
    You should have received a copy of the GNU General Public License
Ivan Mahonin 8cb222
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
Ivan Mahonin 8cb222
*/
Ivan Mahonin 8cb222
Ivan Mahonin 8cb222
using System;
Ivan Mahonin 8cb222
using System.Drawing;
Ivan Mahonin 8cb222
Ivan Mahonin 8cb222
namespace Diagram {
Ivan Mahonin 8cb222
    public static class Geometry {
Ivan Mahonin 8cb222
        public static readonly float precision = 1e-5f;
Ivan Mahonin 8cb222
Ivan Mahonin 8cb222
        public static readonly float[][] splineMatrix = new float[][] {
Ivan Mahonin 8cb222
            new float[] {  2f, -2f,  1f,  1f },
Ivan Mahonin 8cb222
            new float[] { -3f,  3f, -2f, -1f },
Ivan Mahonin 8cb222
            new float[] {  0f,  0f,  1f,  0f },
Ivan Mahonin 8cb222
            new float[] {  1f,  0f,  0f,  0f } };
Ivan Mahonin 8cb222
Ivan Mahonin 8cb222
        // Compare to points place at line base0-base1
Ivan Mahonin 8cb222
        public static int comparePointsAtLine(PointF a0, PointF a1, PointF base0, PointF base1) {
Ivan Mahonin 8cb222
            if (base0.X < base1.X && a0.X < a1.X) return -1;
Ivan Mahonin 8cb222
            if (base0.X < base1.X && a1.X < a0.X) return  1;
Ivan Mahonin 8cb222
            if (base1.X < base0.X && a0.X < a1.X) return  1;
Ivan Mahonin 8cb222
            if (base1.X < base0.X && a1.X < a0.X) return -1;
Ivan Mahonin 8cb222
            if (base0.Y < base1.Y && a0.Y < a1.Y) return -1;
Ivan Mahonin 8cb222
            if (base0.Y < base1.Y && a1.Y < a0.Y) return  1;
Ivan Mahonin 8cb222
            if (base1.Y < base0.Y && a0.Y < a1.Y) return  1;
Ivan Mahonin 8cb222
            if (base1.Y < base0.Y && a1.Y < a0.Y) return -1;
Ivan Mahonin 8cb222
            return 0;
Ivan Mahonin 8cb222
        }
Ivan Mahonin 8cb222
Ivan Mahonin 8cb222
        public static bool findIntersection(PointF a0, PointF a1, PointF b0, PointF b1, out PointF c) {
Ivan Mahonin 8cb222
            c = new PointF(0f, 0f);
Ivan Mahonin 8cb222
            PointF da = new PointF(a1.X - a0.X, a1.Y - a0.Y);
Ivan Mahonin 8cb222
            PointF db = new PointF(b1.X - b0.X, b1.Y - b0.Y);
Ivan Mahonin 8cb222
Ivan Mahonin 8cb222
            float divider = da.X*db.Y - db.X*da.Y;
Ivan Mahonin 8cb222
            if (Math.Abs(divider) < precision) return false;
Ivan Mahonin 8cb222
            float numeratorX = da.X*(b1.Y*b0.X - b0.Y*b1.X)
Ivan Mahonin 8cb222
                             - db.X*(a1.Y*a0.X - a0.Y*a1.X);
Ivan Mahonin 8cb222
            float numeratorY = db.Y*(a1.X*a0.Y - a0.X*a1.Y)
Ivan Mahonin 8cb222
                             - da.Y*(b1.X*b0.Y - b0.X*b1.Y);
Ivan Mahonin 8cb222
            PointF p = new PointF(numeratorX/divider, numeratorY/divider);
Ivan Mahonin 8cb222
            if ( comparePointsAtLine(p, a0, a0, a1) < 0
Ivan Mahonin 8cb222
              || comparePointsAtLine(p, a1, a0, a1) > 0
Ivan Mahonin 8cb222
              || comparePointsAtLine(p, b0, b0, b1) < 0
Ivan Mahonin 8cb222
              || comparePointsAtLine(p, b1, b0, b1) > 0 )
Ivan Mahonin 8cb222
                return false;
Ivan Mahonin 8cb222
Ivan Mahonin 8cb222
            c = p;
Ivan Mahonin 8cb222
            return true;
Ivan Mahonin 8cb222
        }
Ivan Mahonin 8cb222
Ivan Mahonin 8cb222
        public static float lineLength(PointF p0, PointF p1) {
Ivan Mahonin 8cb222
            return (float)Math.Sqrt(
Ivan Mahonin 8cb222
                (p1.X-p0.X)*(p1.X-p0.X)
Ivan Mahonin 8cb222
              + (p1.Y-p0.Y)*(p1.Y-p0.Y) );
Ivan Mahonin 8cb222
        }
Ivan Mahonin 8cb222
Ivan Mahonin 8cb222
        public static PointF pointAtLine(PointF p0, PointF p1, int index = 0, int count = 1, float padding = 0f) {
Ivan Mahonin 8cb222
            float l = lineLength(p0, p1);
Ivan Mahonin 8cb222
            float px = l > precision ? (p1.X - p0.X)*padding/l : 0f;
Ivan Mahonin 8cb222
            float py = l > precision ? (p1.Y - p0.Y)*padding/l : 0f;
Ivan Mahonin 8cb222
            return new PointF(
Ivan Mahonin 8cb222
                (index+1)*(p1.X - p0.X - 2*px)/(count + 1) + p0.X + px,
Ivan Mahonin 8cb222
                (index+1)*(p1.Y - p0.Y - 2*py)/(count + 1) + p0.Y + py);
Ivan Mahonin 8cb222
        }
Ivan Mahonin 8cb222
Ivan Mahonin 8cb222
        public static PointF splineTangent(float s, PointF p0, PointF p1, PointF t0, PointF t1) {
Ivan Mahonin 8cb222
            float h1 = 3f*splineMatrix[0][0]*s*s + 2f*splineMatrix[1][0]*s + splineMatrix[2][0];
Ivan Mahonin 8cb222
            float h2 = 3f*splineMatrix[0][1]*s*s + 2f*splineMatrix[1][1]*s + splineMatrix[2][1];
Ivan Mahonin 8cb222
            float h3 = 3f*splineMatrix[0][2]*s*s + 2f*splineMatrix[1][2]*s + splineMatrix[2][2];
Ivan Mahonin 8cb222
            float h4 = 3f*splineMatrix[0][3]*s*s + 2f*splineMatrix[1][3]*s + splineMatrix[2][3];
Ivan Mahonin 8cb222
            return new PointF(
Ivan Mahonin 8cb222
                p0.X*h1 + p1.X*h2 + t0.X*h3 + t1.X*h4,
Ivan Mahonin 8cb222
                p0.Y*h1 + p1.Y*h2 + t0.Y*h3 + t1.Y*h4);
Ivan Mahonin 8cb222
        }
Ivan Mahonin 8cb222
Ivan Mahonin 8cb222
        public static PointF splinePoint(float s, PointF p0, PointF p1, PointF t0, PointF t1) {
Ivan Mahonin 8cb222
            float h1 = splineMatrix[0][0]*s*s*s + splineMatrix[1][0]*s*s + splineMatrix[2][0]*s + splineMatrix[3][0];
Ivan Mahonin 8cb222
            float h2 = splineMatrix[0][1]*s*s*s + splineMatrix[1][1]*s*s + splineMatrix[2][1]*s + splineMatrix[3][1];
Ivan Mahonin 8cb222
            float h3 = splineMatrix[0][2]*s*s*s + splineMatrix[1][2]*s*s + splineMatrix[2][2]*s + splineMatrix[3][2];
Ivan Mahonin 8cb222
            float h4 = splineMatrix[0][3]*s*s*s + splineMatrix[1][3]*s*s + splineMatrix[2][3]*s + splineMatrix[3][3];
Ivan Mahonin 8cb222
            return new PointF(
Ivan Mahonin 8cb222
                p0.X*h1 + p1.X*h2 + t0.X*h3 + t1.X*h4,
Ivan Mahonin 8cb222
                p0.Y*h1 + p1.Y*h2 + t0.Y*h3 + t1.Y*h4 );
Ivan Mahonin 8cb222
        }
Ivan Mahonin 8cb222
    }
Ivan Mahonin 8cb222
}
Ivan Mahonin 8cb222