我传递的是Points[]
数组,需要确定一个交叉点。在我的测试中,我找到了一个始终显示“No Intersect”的坐标集 - 我需要一种方法来解释这个问题。对于下面给定的坐标,C#中的公式/方程计算交叉点是什么?
private void button1_Click(object sender, EventArgs e)
{
Point[] points = new Point[] { new Point { X = -1000, Y = 70 }, new Point { X = 0, Y = 78 }, new Point { X = 0, Y = 96 }, new Point { X = 1000, Y = 96 } };
PointF returnedPoint = new PointF();
PointF ftp = new PointF();
ftp.X = (float)6;
ftp.Y = (float)91.5;
PointF lsd = new PointF();
lsd.X = (float)0;
lsd.Y = (float)111.285194;
for (int i = 0; i < points.Count() - 1; i++)
{
if (points.Count() - 1 < 0)
{
MessageBox.Show(String.Format("Invalid data input"));
return;
}
if (i != 0)
{
float X1value = points[i].X;
float X2value = points[i - 1].X;
float Y1value = points[i].Y;
float Y2value = points[i - 1].Y;
GetIntersectCoordiates(ftp, lsd, new PointF(X1value, Y1value), new PointF(X2value, Y2value), ref returnedPoint);
}
else { continue; }
if (Convert.ToString(returnedPoint.X) != "0" && Convert.ToString(returnedPoint.Y) != "0")
{
MessageBox.Show(Convert.ToString(returnedPoint.X));
MessageBox.Show(Convert.ToString(returnedPoint.Y));
}
else { MessageBox.Show("There is no intersect point with these coordinates"); }
}
}
bool GetIntersectCoordiates(PointF p1, PointF p2, PointF q1, PointF q2, ref PointF returnedPoint)
{
double x21 = p2.X - p1.X;
double y21 = p2.Y - p1.Y;
double x31 = q1.X - p1.X;
double y31 = q1.Y - p1.Y;
double x43 = q2.X - q1.X;
double y43 = q2.Y - q1.Y;
double PD = x43 * y21 - x21 * y43;
if (PD == 0)
{
return false;
}
double s = (x43 * y31 - x31 * y43) / PD;
double t = (x21 * y31 - x31 * y21) / PD;
if ((s >= 0) && (s <= 1) && (t >= 0) && (t <= 1))
{
returnedPoint.X = (float)(p1.X + (p2.X - p1.X) * s);
returnedPoint.Y = (float)(p1.Y + (p2.Y - p1.Y) * s);
return true;
}
return false;
}
答案 0 :(得分:0)
目前还不清楚你在这里要做什么。我将提供一个迷你几何库,其中Vector2
类包含(x,y)
类型值,Point2
使用齐次坐标保持平面位置,Line2
保持平面线也使用齐次坐标
Geometry
静态类中定义了一些常见操作,如连接点以形成线,或相交线来形成点。
这是例如如何使用此库:
static class Program
{
static void Main(string[] args)
{
// Start Program Here
// Define three points, A, B, & C
Point2 A = Point2.FromCoordinates(3, -1);
Point2 B = Point2.FromCoordinates(0.8, 2);
Point2 C = Point2.FromCoordinates(-1, 0.2);
// Get a line between A & B
Line2 AB = Line2.FromTwoPoints(A, B);
// Get point on line closest to C
Point2 D = Geometry.Closest(AB, C);
// Check distance between C & AB equals distance between C & D
double d_CAB = Geometry.Distance(C, AB);
double d_CD = Geometry.Distance(C, D);
double diff = d_CAB-d_CD;
// Check that D is coincident to AB
bool check_DAB = Geometry.AreNear(D, AB);
// Get a line between C & D
Line2 CD = Line2.FromTwoPoints(C, D);
// Get a line @ C parallel to AB
Line2 L = Line2.ThroughPointParallelToLine(C, AB);
double d_CAB2 = Geometry.Distance(L, AB);
double diff2 = d_CAB2-d_CAB;
// Get a line @ C perpendicular to AB
Line2 M = Line2.ThroughPointNormalToLine(C, AB);
// Check intersection of M and AB that is actually point D
bool check_DM = Geometry.AreNear(D, Geometry.Meet(M, AB));
}
}
和我写的那个库(需要VS2015 +)
using static System.Math;
using PointF = System.Drawing.PointF;
public struct Vector2 : IEquatable<Vector2>
{
public Vector2(double x, double y) { this.X=x; this.Y=y; }
public static readonly Vector2 Zero = new Vector2(0, 0);
public static readonly Vector2 UnitX = new Vector2(1, 0);
public static readonly Vector2 UnitY = new Vector2(0, 1);
public double Magnitude => Math.Sqrt(X*X+Y*Y);
public Vector2 Direction => Normalized();
public double X { get; }
public double Y { get; }
public bool IsZero => X*X+Y*Y==0;
public Vector2 Normalized() => Magnitude>0 ? this/Magnitude : Zero;
public static Vector2 operator +(Vector2 a, Vector2 b)
{
return new Vector2(a.X+b.X, a.Y+b.Y);
}
public static Vector2 operator -(Vector2 a, Vector2 b)
{
return new Vector2(a.X-b.X, a.Y-b.Y);
}
public static Vector2 operator *(double f, Vector2 a)
{
return new Vector2(f*a.X, f*a.Y);
}
public static Vector2 operator *(Vector2 a, double f) { return f*a; }
public static Vector2 operator /(Vector2 a, double d) { return (1/d)*a; }
public override bool Equals(object obj)
{
if (obj is Vector2)
{
return Equals((Vector2)obj);
}
return false;
}
public bool Equals(Vector2 other)
{
return X==other.X&&Y==other.Y;
}
public static bool operator ==(Vector2 u, Vector2 v)
{
return u.Equals(v);
}
public static bool operator !=(Vector2 u, Vector2 v)
{
return !(u==v);
}
public override int GetHashCode()
{
unchecked
{
int hc = 17;
hc=23*hc+X.GetHashCode();
hc=23*hc+Y.GetHashCode();
return hc;
}
}
}
public struct Point2
{
/// <summary>
/// Define a point by three homogeneous coordinates
/// </summary>
public Point2(double u, double v, double w)
{
this.U=u;
this.V=v;
this.W=w;
}
/// <summary>
/// Define a point from (x,y) coordinates
/// </summary>
public static Point2 FromCoordinates(double x, double y)
{
return new Point2(x, y, 1);
}
/// <summary>
/// Define a point from vector coordinates
/// </summary>
public static Point2 FromCoordinates(Vector2 r)
{
return new Point2(r.X, r.Y, 1);
}
/// <summary>
/// Get point along a direction, at a certain distance
/// </summary>
/// <param name="n">The direction</param>
/// <param name="d">The distance</param>
public static Point2 FromDirectionAndDistance(Vector2 n, double d)
{
n=n.Direction;
return new Point2(d*n.X, d*n.Y, 1);
}
/// <summary>
/// Define a point where two lines meet (intersection)
/// </summary>
public static Point2 FromTwoLiness(Line2 m, Line2 n) { return Geometry.Meet(m, n); }
/// <summary>
/// A point at the origin
/// </summary>
public static readonly Point2 Origin = new Point2(0, 0, 1);
/// <summary>
/// A point on the unit x-axis
/// </summary>
public static readonly Point2 OneX = new Point2(1, 0, 1);
/// <summary>
/// A point on the unit y-axis
/// </summary>
public static readonly Point2 OneY = new Point2(0, 1, 1);
/// <summary>
/// First point at the horizon (infinity)
/// </summary>
public static readonly Point2 I = new Point2(1, 0, 0);
/// <summary>
/// Second point at the horizon (infinity);
/// </summary>
public static readonly Point2 J = new Point2(0, 1, 0);
public double U { get; }
public double V { get; }
public double W { get; }
public Point2 Normalized() => FromCoordinates(Coordinates);
public bool IsFinite => !IsInfinite;
public bool IsInfinite => W==0;
/// <summary>
/// The (x,y) coordinates of the point
/// </summary>
public Vector2 Coordinates => new Vector2(U/W, V/W);
/// <summary>
/// The center is at the point
/// </summary>
public Point2 Center => this;
/// <summary>
/// The direction is from the origin to the point
/// </summary>
public Vector2 Direction => new Vector2(U, V).Direction;
/// <summary>
/// The distance to the origin
/// </summary>
public double Distance => Sqrt(U*U+V*V)/Magnitude;
/// <summary>
/// The magnitude is weight of the point
/// </summary>
public double Magnitude => W;
/// <summary>
/// Offset a point by a vector
/// </summary>
/// <param name="p">The point</param>
/// <param name="e">The offset vector</param>
/// <returns>A new point</returns>
public static Point2 operator +(Point2 p, Vector2 e)
{
return new Point2(p.U+p.W*e.X, p.V+p.W*e.Y, p.W);
}
/// <summary>
/// Get the offset between two points
/// </summary>
public static Vector2 operator -(Point2 p, Point2 q)
{
return p.Coordinates-q.Coordinates;
}
/// <summary>
/// Inner product between point and line. This is proportional to the distance
/// and hence it is zero when the point is on the line.
/// </summary>
public static double operator *(Point2 p, Line2 m)
{
return m.A*p.U+m.B*p.V+m.C*p.W;
}
/// <summary>
/// Defines the point joint operator (cross product) between two points
/// </summary>
public static Line2 operator ^(Point2 p, Point2 q) { return Geometry.Join(p, q); }
/// <summary>
/// Conversion between Point2 and PointF
/// </summary>
public static implicit operator PointF(Point2 p)
{
return new PointF((float)(p.U/p.W), (float)(p.V/p.W));
}
}
public struct Line2
{
/// <summary>
/// Define a line by three coefficients (a,b,c) such that the
/// equation of the line is `a*x+b*y+c=0`
/// </summary>
public Line2(double a, double b, double c)
{
this.A=a;
this.B=b;
this.C=c;
}
/// <summary>
/// Define a line joining two points
/// </summary>
public static Line2 FromTwoPoints(Point2 p, Point2 q) { return Geometry.Join(p, q); }
/// <summary>
/// Define a line along a directrion and through a point
/// </summary>
/// <param name="p">The point</param>
/// <param name="e">The direction</param>
public static Line2 ThroughPointAlongDirection(Point2 p, Vector2 e)
{
return new Line2(-p.W*e.Y, p.W*e.X, p.U*e.Y-p.V*e.X);
}
/// <summary>
/// Define a line parallel to another line and through a point
/// </summary>
/// <param name="p">The point</param>
/// <param name="m">The other line</param>
/// <returns></returns>
public static Line2 ThroughPointParallelToLine(Point2 p, Line2 m)
{
return new Line2(m.A*p.W, m.B*p.W, -m.A*p.U-m.B*p.V);
}
/// <summary>
/// Define a line perpendicular to another line and through a point
/// </summary>
/// <param name="p">The point</param>
/// <param name="m">The other line</param>
/// <returns></returns>
public static Line2 ThroughPointNormalToLine(Point2 p, Line2 m)
{
return new Line2(-m.B*p.W, m.A*p.W, m.B*p.U-m.A*p.V);
}
/// <summary>
/// Define a line normal to a direction and a certain distance from the origin
/// </summary>
/// <param name="n">The normal vector</param>
/// <param name="d">The distance. Positive & negative values are valid</param>
public static Line2 FromNormalAndDistance(Vector2 n, double d)
{
return new Line2(n.X, n.Y, -d*n.Magnitude);
}
/// <summary>
/// Define a line along a direction and a certain distance from the origin
/// </summary>
/// <param name="e">The direction vector</param>
/// <param name="d">The distance. Positive & negative values are valid</param>
public static Line2 FromDirectionAndDistance(Vector2 e, double d)
{
return new Line2(-e.Y, e.X, -d*e.Magnitude);
}
/// <summary>
/// X-axis is the line defined by `y=0`
/// </summary>
public static readonly Line2 XAxis = new Line2(0, 1, 0);
/// <summary>
/// Y-axis is the line defined by `x=0`
/// </summary>
public static readonly Line2 YAxis = new Line2(1, 0, 0);
/// <summary>
/// The horizon is the unique line at infinity
/// </summary>
public static readonly Line2 Horizon = new Line2(0, 0, 1);
public double A { get; }
public double B { get; }
public double C { get; }
public Line2 Normalized() => FromNormalAndDistance(Normal, Distance);
public bool IsFinite => !IsInfinite;
public bool IsInfinite => A*A+B*B==0;
/// <summary>
/// The center of the line is the point on the line closest to the origin
/// </summary>
public Point2 Center => new Point2(-A*C, -B*C, A*A+B*B);
/// <summary>
/// The direction vector along the line
/// </summary>
public Vector2 Direction => new Vector2(-B, A).Direction;
/// <summary>
/// The normal vector to the line
/// </summary>
public Vector2 Normal => new Vector2(A, B).Direction;
/// <summary>
/// The closest distance of the line to the origin
/// </summary>
public double Distance => C/Magnitude;
/// <summary>
/// The magnitude of the line is norm of the [A,B] vector
/// </summary>
public double Magnitude => Sqrt(A*A+B*B);
/// <summary>
/// Offset a line by a vector.
/// </summary>
/// <param name="a">The line</param>
/// <param name="e">The offset vector</param>
/// <returns>A parallel line</returns>
public static Line2 operator +(Line2 a, Vector2 e)
{
return new Line2(a.A, a.B, a.C-a.A*e.X-a.B*e.Y);
}
/// <summary>
/// Get the offset vector of two parallel lines
/// </summary>
public static Vector2 operator -(Line2 m, Line2 n)
{
return Geometry.IsParallel(m, n) ? m.Normal*Geometry.Distance(m, n) : Vector2.Zero;
}
/// <summary>
/// Inner product between point and line. This is proportional to the distance
/// and hence it is zero when the point is on the line.
/// </summary>
public static double operator *(Line2 m, Point2 p)
{
return m.A*p.U+m.B*p.V+m.C*p.W;
}
/// <summary>
/// Defines the line meet operator (cross product) between two lines
/// </summary>
public static Point2 operator ^(Line2 m, Line2 n) { return Geometry.Meet(m, n); }
}
public static class Geometry
{
public static double Dot(Point2 p, Line2 m) { return p * m; }
public static double Dot(Line2 m, Point2 p) { return m * p; }
public static Point2 Cross(Line2 m, Line2 n) { return m ^ n; }
public static Line2 Cross(Point2 p, Point2 q) { return p ^ q; }
/// <summary>
/// Check for parallelism between two lines. Due to roundoff errors
/// this will return false when lines are almost parallel.
/// </summary>
public static bool IsParallel(Line2 m, Line2 n)
{
return m.A*n.B-m.B*n.A==0;
}
/// <summary>
/// Check for coincidence between two points. Due to roundoff errors
/// this will return false when two points are nearly coincident.
/// </summary>
public static bool IsCoincident(Point2 p, Point2 q)
{
return p.U*q.W-q.U*p.W==0
&&p.V*q.W-q.V*p.V==0;
}
/// <summary>
/// Check for parallelism and separation between two lines
/// </summary>
public static bool IsCoincident(Line2 m, Line2 n)
{
return IsParallel(m, n)&& Distance(m,n)==0;
}
/// <summary>
/// Check if a line is passing through a point
/// </summary>
public static bool IsCoincident(Line2 m, Point2 p) => IsCoincident(p, m);
/// <summary>
/// Check if point lies on a line
/// </summary>
public static bool IsCoincident(Point2 p, Line2 m)
{
return p*m==0;
}
/// <summary>
/// Check if two points are near each other within tolerance
/// </summary>
public static bool AreNear(Point2 p, Point2 q, double tolerance = 1e-12)
{
p=p.Normalized();
q=q.Normalized();
return Distance(p, q)<=tolerance;
}
/// <summary>
/// Check if a point is almost on a line within tolerance
/// </summary>
public static bool AreNear(Point2 p, Line2 m, double tolerance = 1e-12)
{
p=p.Normalized();
m=m.Normalized();
return Distance(p, m)<=tolerance;
}
/// <summary>
/// Check that two lines are almost parallel within tolerance
/// </summary>
public static bool AreAlmostParallel(Line2 m, Line2 n, double tolerance = 1e-12)
{
m=m.Normalized();
n=n.Normalized();
return Math.Abs(m.A*n.B-m.B*n.A)<=tolerance;
}
/// <summary>
/// The point where two lines meet.
/// </summary>
public static Point2 Meet(Line2 m, Line2 n)
{
// | ma | | na | | (mb*nc-mc*nb) |
// | mb | × | nb | = |-(ma*nc-mc*na) |
// | mc | | nc | | ma*nb-mb*na |
return new Point2(
m.B*n.C-m.C*n.B,
m.C*n.A-m.A*n.C,
m.A*n.B-m.B*n.A);
}
/// <summary>
/// The line joining two points
/// </summary>
public static Line2 Join(Point2 p, Point2 q)
{
// | px | | qx | | (py-qy) |
// | py | × | qy | = | -(px-qx) |
// | 1 | | 1 | | px*qy-py*qx |
return new Line2(
p.V*q.W-p.W*q.V,
p.W*q.U-p.U*q.W,
p.U*q.V-p.V*q.U);
}
/// <summary>
/// Calculate the cartesian distance between two points
/// </summary>
public static double Distance(Point2 p, Point2 q)
{
var u = p.U*q.W-q.U*p.W;
var v = p.V*q.W-q.V*p.W;
return Sqrt(u*u+v*v)/(p.W*q.W);
}
/// <summary>
/// Calculate the offset of a line from a point
/// </summary>
public static double Distance(Line2 m, Point2 p) => Distance(p, m);
/// <summary>
/// Calculate the closest distance of a line to a point
/// </summary>
public static double Distance(Point2 p, Line2 m)
{
// Use the inner product `m*p = A*U+B*V+C*W`
return Abs(m*p)/(p.W*m.Magnitude);
}
/// <summary>
/// Calculate the distance between paralllel lines.
/// Returns 0 if lines intersect or are coincident.
/// </summary>
public static double Distance(Line2 m, Line2 n)
{
// Check that lines are parallel
if (IsParallel(m,n))
{
return n.Distance-m.Distance;
}
// If they intersect, the distance is zero
return 0;
}
/// <summary>
/// Get point on line closet to some other point
/// </summary>
/// <param name="m">The line</param>
/// <param name="p">The other point</param>
/// <returns>A point on the line</returns>
public static Point2 Closest(Line2 m, Point2 p)
{
return new Point2(
m.B*m.B*p.U-m.A*(m.B*p.V+m.C*p.W),
m.A*m.A*p.V-m.B*(m.A*p.U+m.C*p.W),
p.W*(m.A*m.A+m.B*m.B));
}
}
参考:http://robotics.stanford.edu/~birch/projective/node4.html