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