Esempio n. 1
0
        public bool Hits(
            Cylinder3d cylinder,
            double tmin, double tmax,
            ref RayHit3d hit)
        {
            var intersects = HitsCylinder(cylinder, tmin, tmax, ref hit);

            return(intersects);
        }
Esempio n. 2
0
        public bool HitsCylinder(Cylinder3d cylinder,
                                 double tmin, double tmax,
                                 ref RayHit3d hit)
        {
            var axisDir = cylinder.Axis.Direction.Normalized;

            // Vector Cyl.P0 -> Ray.Origin
            var op = Origin - cylinder.P0;

            // normal RayDirection - CylinderAxis
            var normal     = Direction.Cross(axisDir);
            var unitNormal = normal.Normalized;

            // normal (Vec Cyl.P0 -> Ray.Origin) - CylinderAxis
            var normal2 = op.Cross(axisDir);
            var t       = -normal2.Dot(unitNormal) / normal.Length;

            var radius = cylinder.Radius;

            if (cylinder.DistanceScale != 0)
            {   // cylinder gets bigger, the further away it is
                var pnt = GetPointOnRay(t);

                var dis = V3d.Distance(pnt, this.Origin);
                radius = ((cylinder.Radius / cylinder.DistanceScale) * dis) * 2;
            }

            // between enitre rays (caps are ignored)
            var shortestDistance = Fun.Abs(op.Dot(unitNormal));

            if (shortestDistance <= radius)
            {
                var s = Fun.Abs(Fun.Sqrt(radius.Square() - shortestDistance.Square()) / Direction.Length);

                var t1 = t - s; // first hit of Cylinder shell
                var t2 = t + s; // second hit of Cylinder shell

                if (t1 > tmin && t1 < tmax)
                {
                    tmin = t1;
                }
                if (t2 < tmax && t2 > tmin)
                {
                    tmax = t2;
                }

                hit.T     = t1;
                hit.Point = GetPointOnRay(t1);

                // check if found point is outside of Cylinder Caps
                var bottomPlane  = new Plane3d(cylinder.Circle0.Normal, cylinder.Circle0.Center);
                var topPlane     = new Plane3d(cylinder.Circle1.Normal, cylinder.Circle1.Center);
                var heightBottom = bottomPlane.Height(hit.Point);
                var heightTop    = topPlane.Height(hit.Point);
                // t1 lies outside of caps => find closest cap hit
                if (heightBottom > 0 || heightTop > 0)
                {
                    hit.T = tmax;
                    // intersect with bottom Cylinder Cap
                    var bottomHit = HitsPlane(bottomPlane, tmin, tmax, ref hit);
                    // intersect with top Cylinder Cap
                    var topHit = HitsPlane(topPlane, tmin, tmax, ref hit);

                    // hit still close enough to cylinder axis?
                    var distance = cylinder.Axis.Ray3d.GetMinimalDistanceTo(hit.Point);

                    if (distance <= radius && (bottomHit || topHit))
                    {
                        return(true);
                    }
                }
                else
                {
                    return(true);
                }
            }

            hit.T     = tmax;
            hit.Point = V3d.NaN;
            return(false);
        }
Esempio n. 3
0
 public static bool ApproximateEquals(this Cylinder3d a, Cylinder3d b)
 => ApproximateEquals(a, b, Constant <double> .PositiveTinyValue);
Esempio n. 4
0
 public bool Equals(Cylinder3d other) =>
 P0.Equals(other.P0) &&
 P1.Equals(other.P1) &&
 Radius.Equals(other.Radius) &&
 DistanceScale.Equals(other.DistanceScale);
Esempio n. 5
0
 public static bool ApproximateEquals(this Cylinder3d a, Cylinder3d b, double tolerance) =>
 ApproximateEquals(a.P0, b.P0, tolerance) &&
 ApproximateEquals(a.P1, b.P1, tolerance) &&
 ApproximateEquals(a.Radius, b.Radius, tolerance) &&
 ApproximateEquals(a.DistanceScale, b.DistanceScale, tolerance);