/// <summary> /// Get intersection of segment with triangle. /// Returns 'null' (no intersection) or object of type 'Point3d' or 'Segment3d'. /// </summary> public object IntersectionWith(Segment3d s) { // Relative tolerance ================================ if (!GeometRi3D.UseAbsoluteTolerance) { double tol = GeometRi3D.Tolerance; GeometRi3D.Tolerance = tol * Max(s.Length, Max(AB, Max(BC, AC))); GeometRi3D.UseAbsoluteTolerance = true; object result = this.IntersectionWith(s); GeometRi3D.UseAbsoluteTolerance = false; GeometRi3D.Tolerance = tol; return(result); } //==================================================== object obj = this.IntersectionWith(s.ToLine); if (obj == null) { return(null); } else if (obj.GetType() == typeof(Point3d)) { Point3d p = (Point3d)obj; if (p.BelongsTo(s)) { return(p); } else { return(null); } } else { return(s.IntersectionWith((Segment3d)obj)); } }
/// <summary> /// Intersection of two circles. /// Returns 'null' (no intersection) or object of type 'Circle3d', 'Point3d' or 'Segment3d'. /// In 2D (coplanar circles) the segment will define two intersection points. /// </summary> public object IntersectionWith(Circle3d c) { // Relative tolerance ================================ if (!GeometRi3D.UseAbsoluteTolerance) { double tol = GeometRi3D.Tolerance; GeometRi3D.Tolerance = tol * Max(this.R, c.R); GeometRi3D.UseAbsoluteTolerance = true; object result = this.IntersectionWith(c); GeometRi3D.UseAbsoluteTolerance = false; GeometRi3D.Tolerance = tol; return(result); } //==================================================== if (this.Normal.IsParallelTo(c.Normal)) { if (this.Center.BelongsTo(new Plane3d(c.Center, c.Normal))) { // Coplanar objects // Search 2D intersection of two circles // Equal circles if (this.Center == c.Center && GeometRi3D.AlmostEqual(this.R, c.R)) { return(this.Copy()); } double d = this.Center.DistanceTo(c.Center); // Separated circles if (GeometRi3D.Greater(d, this.R + c.R)) { return(null); } // One circle inside the other if (d < Abs(this.R - c.R) - GeometRi3D.Tolerance) { return(null); } // Outer tangency if (GeometRi3D.AlmostEqual(d, this.R + c.R)) { Vector3d vec = new Vector3d(this.Center, c.Center); return(this.Center.Translate(this.R * vec.Normalized)); } // Inner tangency if (Abs(Abs(this.R - c.R) - d) < GeometRi3D.Tolerance) { Vector3d vec = new Vector3d(this.Center, c.Center); if (this.R > c.R) { return(this.Center.Translate(this.R * vec.Normalized)); } else { return(this.Center.Translate(-this.R * vec.Normalized)); } } // intersecting circles // Create local CS with origin in circle's center Vector3d vec1 = new Vector3d(this.Center, c.Center); Vector3d vec2 = vec1.Cross(this.Normal); Coord3d local_cs = new Coord3d(this.Center, vec1, vec2); double x = 0.5 * (d * d - c.R * c.R + this.R * this.R) / d; double y = 0.5 * Sqrt((-d + c.R - this.R) * (-d - c.R + this.R) * (-d + c.R + this.R) * (d + c.R + this.R)) / d; Point3d p1 = new Point3d(x, y, 0, local_cs); Point3d p2 = new Point3d(x, -y, 0, local_cs); return(new Segment3d(p1, p2)); } else { // parallel objects return(null); } } else { // Check 3D intersection Plane3d plane = new Plane3d(this.Center, this.Normal); object obj = plane.IntersectionWith(c); if (obj == null) { return(null); } else if (obj.GetType() == typeof(Point3d)) { Point3d p = (Point3d)obj; if (p.BelongsTo(c)) { return(p); } else { return(null); } } else { Segment3d s = (Segment3d)obj; return(s.IntersectionWith(this)); } } }
/// <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 line with segment. /// Returns 'null' (no intersection) or object of type 'Point3d' or 'Segment3d'. /// </summary> public object IntersectionWith(Segment3d s) { return(s.IntersectionWith(this)); }