public double DistanceTo(Segment3d s) { if (this.Center.ProjectionTo(s.ToLine).BelongsTo(s)) { return(this.DistanceTo(s.ToLine)); } else { return(Min(this.DistanceTo(s.P1), this.DistanceTo(s.P2))); } }
/// <summary> /// Return Axis Aligned Bounding Box (AABB) in given coordinate system. /// </summary> public Box3d BoundingBox(Coord3d coord = null) { coord = (coord == null) ? Coord3d.GlobalCS : coord; Line3d l1 = new Line3d(coord.Origin, coord.Xaxis); Line3d l2 = new Line3d(coord.Origin, coord.Yaxis); Line3d l3 = new Line3d(coord.Origin, coord.Zaxis); Segment3d s1 = this.ProjectionTo(l1); Segment3d s2 = this.ProjectionTo(l2); Segment3d s3 = this.ProjectionTo(l3); return(new Box3d(_point, s1.Length, s2.Length, s3.Length, coord)); }
/// <summary> /// Return Axis Aligned Bounding Box (AABB) in given coordinate system. /// </summary> public Box3d BoundingBox(Coord3d coord = null) { coord = (coord == null) ? Coord3d.GlobalCS : coord; Line3d l1 = new Line3d(coord.Origin, coord.Xaxis); Line3d l2 = new Line3d(coord.Origin, coord.Yaxis); Line3d l3 = new Line3d(coord.Origin, coord.Zaxis); double px, py, pz, lx, ly, lz; Segment3d s = this.ProjectionTo(l1); px = (0.5 * (s.P1 + s.P2)).ConvertTo(coord).X; lx = s.Length; s = this.ProjectionTo(l2); py = (0.5 * (s.P1 + s.P2)).ConvertTo(coord).Y; ly = s.Length; s = this.ProjectionTo(l3); pz = (0.5 * (s.P1 + s.P2)).ConvertTo(coord).Z; lz = s.Length; return(new Box3d(new Point3d(px, py, pz, coord), lx, ly, lz, coord)); }
/// <summary> /// Determines whether two objects are equal. /// </summary> public override bool Equals(object obj) { if (obj == null || (!object.ReferenceEquals(this.GetType(), obj.GetType()))) { return(false); } Segment3d s = (Segment3d)obj; if (GeometRi3D.UseAbsoluteTolerance) { return((this.P1 == s.P1 && this.P2 == s.P2) | (this.P1 == s.P2 && this.P2 == s.P1)); } else { double tol = GeometRi3D.Tolerance; GeometRi3D.Tolerance = tol * this.Length; GeometRi3D.UseAbsoluteTolerance = true; bool result = (this.P1 == s.P1 && this.P2 == s.P2) | (this.P1 == s.P2 && this.P2 == s.P1); GeometRi3D.UseAbsoluteTolerance = false; GeometRi3D.Tolerance = tol; return(result); } }
/// <summary> /// Shortest distance between line and segment /// </summary> public double DistanceTo(Segment3d s) { return(s.DistanceTo(this)); }
/// <summary> /// Returns shortest distance between two segments /// </summary> public double DistanceTo(Segment3d s) { // Algorithm by Dan Sunday // http://geomalgorithms.com/a07-_distance.html double small = GeometRi3D.Tolerance; Vector3d u = this.ToVector; Vector3d v = s.ToVector; Vector3d w = new Vector3d(s.P1, this.P1); double a = u * u; double b = u * v; double c = v * v; double d = u * w; double e = v * w; double DD = a * c - b * b; double sc = 0; double sN = 0; double sD = 0; double tc = 0; double tN = 0; double tD = 0; sD = DD; tD = DD; if (DD < small) { // the lines are almost parallel, force using point Me.P1 to prevent possible division by 0.0 later sN = 0.0; sD = 1.0; tN = e; tD = c; } else { // get the closest points on the infinite lines sN = (b * e - c * d); tN = (a * e - b * d); if ((sN < 0.0)) { // sc < 0 => the s=0 edge Is visible sN = 0.0; tN = e; tD = c; } else if ((sN > sD)) { // sc > 1 => the s=1 edge Is visible sN = sD; tN = e + b; tD = c; } } if ((tN < 0.0)) { // tc < 0 => the t=0 edge Is visible tN = 0.0; // recompute sc for this edge if ((-d < 0.0)) { sN = 0.0; } else if ((-d > a)) { sN = sD; } else { sN = -d; sD = a; } } else if ((tN > tD)) { // tc > 1 => the t=1 edge Is visible tN = tD; // recompute sc for this edge if (((-d + b) < 0.0)) { sN = 0; } else if (((-d + b) > a)) { sN = sD; } else { sN = (-d + b); sD = a; } } // finally do the division to get sc And tc sc = Abs(sN) < small ? 0.0 : sN / sD; tc = Abs(tN) < small ? 0.0 : tN / tD; // get the difference of the two closest points Vector3d dP = w + (sc * u) - (tc * v); // = S1(sc) - S2(tc) return(dP.Norm); }