/// <summary> /// Point on the perpendicular to the line /// </summary> public Point3d PerpendicularTo(Line3d l) { Vector3d r1 = this.Point.ToVector; Vector3d r2 = l.Point.ToVector; Vector3d s1 = this.Direction; Vector3d s2 = l.Direction; if (s1.Cross(s2).Norm > GeometRi3D.Tolerance) { Point3d p = l.PerpendicularTo(new Line3d(this.Point, this.Direction)); if (p.BelongsTo(this)) { r1 = r2 + (r2 - r1) * s1.Cross(s1.Cross(s2)) / (s1 * s2.Cross(s1.Cross(s2))) * s2; return(r1.ToPoint); } else { return(this.Point.ProjectionTo(l)); } } else { throw new Exception("Lines are parallel"); } }
/// <summary> /// Shortest distance to a line /// </summary> public double DistanceTo(Line3d l) { Vector3d r1 = this.Point.ToVector; Vector3d r2 = l.Point.ToVector; Vector3d s1 = this.Direction; Vector3d s2 = l.Direction; if (s1.Cross(s2).Norm > GeometRi3D.Tolerance) { // Crossing lines Point3d p = l.PerpendicularTo(new Line3d(this.Point, this.Direction)); if (p.BelongsTo(this)) { return(Abs((r2 - r1) * s1.Cross(s2)) / s1.Cross(s2).Norm); } else { return(this.Point.DistanceTo(l)); } } else { // Parallel lines return((r2 - r1).Cross(s1).Norm / s1.Norm); } }
/// <summary> /// Returns shortest distance from segment to the line /// </summary> public double DistanceTo(Line3d l) { if (l.PerpendicularTo(this.ToLine).BelongsTo(this)) { return(l.DistanceTo(this.ToLine)); } else { return(Min(this.P1.DistanceTo(l), this.P2.DistanceTo(l))); } }
/// <summary> /// Get intersection of line with other line. /// Returns 'null' (no intersection) or object of type 'Point3d' or 'Line3d'. /// </summary> public object IntersectionWith(Line3d l) { if (l.IsParallelTo(this) && l.Point.BelongsTo(this)) { return(this.Copy()); } Point3d p = l.PerpendicularTo(this); if (p.BelongsTo(l)) { return(p); } else { return(null); } }
/// <summary> /// Get intersection of segment with line. /// Returns 'null' (no intersection) or object of type 'Point3d' or 'Segment3d'. /// </summary> public object IntersectionWith(Line3d l) { if (this.BelongsTo(l)) { return(this.Copy()); } Point3d p = l.PerpendicularTo(this.ToLine); if (p.BelongsTo(this) && p.BelongsTo(l)) { return(p); } else { return(null); } }
/// <summary> /// Get intersection of segment with other segment. /// Returns 'null' (no intersection) or object of type 'Point3d' or 'Segment3d'. /// </summary> public object IntersectionWith(Segment3d s) { if (this == s) { return(this.Copy()); } Line3d l1 = this.ToLine; Line3d l2 = s.ToLine; if (this.BelongsTo(l2) || s.BelongsTo(l1)) { // Segments are collinear // Relative tolerance check ================================ double tol = GeometRi3D.Tolerance; if (!GeometRi3D.UseAbsoluteTolerance) { tol = GeometRi3D.Tolerance * Max(this.Length, s.Length); } //========================================================== // Create local CS with X-axis along segment 's' Vector3d v2 = s.ToVector.OrthogonalVector; Coord3d cs = new Coord3d(s.P1, s.ToVector, v2); double x1 = 0.0; double x2 = s.Length; double t3 = this.P1.ConvertTo(cs).X; double t4 = this.P2.ConvertTo(cs).X; double x3 = Min(t3, t4); double x4 = Max(t3, t4); // Segments do not overlap if (GeometRi3D.Smaller(x4, x1, tol) || GeometRi3D.Greater(x3, x2, tol)) { return(null); } // One common point if (GeometRi3D.AlmostEqual(Max(x3, x4), x1, tol)) { return(new Point3d(x1, 0, 0, cs)); } if (GeometRi3D.AlmostEqual(Min(x3, x4), x2, tol)) { return(new Point3d(x2, 0, 0, cs)); } // Overlaping segments x1 = Max(x1, x3); x2 = Min(x2, x4); return(new Segment3d(new Point3d(x1, 0, 0, cs), new Point3d(x2, 0, 0, cs))); } else { Point3d p = l1.PerpendicularTo(l2); if (p.BelongsTo(this) && p.BelongsTo(s)) { return(p); } else { return(null); } } }