2017-09-30 18 views
2

Je passe dans un tableau de Points[] et j'ai besoin de déterminer un point d'intersection. Dans mes tests, j'ai trouvé un ensemble de coordonnées qui montrera toujours que "No Intersect" - et j'ai besoin d'un moyen de rendre compte de cela. Pour les coordonnées données ci-dessous, quelle serait la formule/équation en C# pour calculer le point d'intersection?Trouver où coordonnées Intersect

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; 
} 
+1

La question manque détails. Que définissez-vous comme l'intersection d'un seul point avec un nuage de points? Le tableau de points est une forme fermée (polygone) ou des lignes définies par toutes les combinaisons de points. – ja72

+0

@ ja72 - Je ne suis pas sûr de ce que vous demandez des éclaircissements? – BellHopByDayAmetuerCoderByNigh

+0

"Je passe dans un tableau de Points [] et j'ai besoin de déterminer un point d'intersection." Comment définissez-vous une intersection de plusieurs points? Pouvez-vous donner un exemple? – ja72

Répondre

0

On ne sait pas ce que vous essayez de faire ici. Je vais offrir une bibliothèque de mini-géométrie avec des classes pour Vector2 détenant des valeurs de type (x,y), Point2 tenant des emplacements planaires en utilisant des coordonnées homogènes et Line2 maintenant des lignes planaires en utilisant également des coordonnées homogènes.

Certaines des opérations courantes telles que les points de jonction pour former des lignes ou les lignes qui se croisent pour former des points sont définies dans la classe statique Geometry.

Ceci est par exemple comment utiliser cette bibliothèque:

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)); 
    } 
} 

et la bibliothèque comme je l'ai écrit (nécessite 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)); 
    } 
} 

Référence: http://robotics.stanford.edu/~birch/projective/node4.html