/// <summary> /// Get intersection of line with triangle. /// Returns 'null' (no intersection) or object of type 'Point3d' or 'Segment3d'. /// </summary> public object IntersectionWith(Line3d l) { // Relative tolerance ================================ if (!GeometRi3D.UseAbsoluteTolerance) { double tol = GeometRi3D.Tolerance; GeometRi3D.Tolerance = tol * Max(AB, Max(BC, AC)); GeometRi3D.UseAbsoluteTolerance = true; object result = this.IntersectionWith(l); GeometRi3D.UseAbsoluteTolerance = false; GeometRi3D.Tolerance = tol; return(result); } //==================================================== Plane3d s = new Plane3d(this.A, this.Normal); object obj = l.IntersectionWith(s); if (obj == null) { return(null); } else { if (obj.GetType() == typeof(Line3d)) { Segment3d sAB = new Segment3d(A, B); Segment3d sBC = new Segment3d(B, C); Segment3d sAC = new Segment3d(A, C); // Line coincides with one side, return segment if (sAB.BelongsTo(l)) { return(sAB); } if (sBC.BelongsTo(l)) { return(sBC); } if (sAC.BelongsTo(l)) { return(sAC); } Point3d pAB = (Point3d)sAB.IntersectionWith(l); Point3d pBC = (Point3d)sBC.IntersectionWith(l); Point3d pAC = (Point3d)sAC.IntersectionWith(l); bool bAB = (object.ReferenceEquals(null, pAB)) ? false : pAB.BelongsTo(sAB); bool bAC = (object.ReferenceEquals(null, pAC)) ? false : pAC.BelongsTo(sAC); bool bBC = (object.ReferenceEquals(null, pBC)) ? false : pBC.BelongsTo(sBC); // Line crosses one corner, return point if (bAB && bBC && pAB == pBC && !bAC) { return(pAB); } if (bAB && bAC && pAB == pAC && !bBC) { return(pAB); } if (bAC && bBC && pAC == pBC && !bAB) { return(pAC); } // Line crosses two sides, return segment if (bAB && bBC && !bAC) { return(new Segment3d(pAB, pBC)); } if (bAB && bAC && !bBC) { return(new Segment3d(pAB, pAC)); } if (bAC && bBC && !bAB) { return(new Segment3d(pAC, pBC)); } // Line crosses one corner and one side, return segment if (pAB == pBC && bAC) { return(new Segment3d(pAB, pAC)); } if (pAB == pAC && bBC) { return(new Segment3d(pAB, pBC)); } if (pAC == pBC && bAB) { return(new Segment3d(pAB, pAC)); } //else return(null); } else { // result of intersection is point Point3d p = (Point3d)obj; if (p.BelongsTo(this)) { 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); } } }