コード例 #1
0
        // from https://cesiumjs.org/2013/05/09/Computing-the-horizon-occlusion-point/
        public static Vector3 FromPoints(ref Vector3[] points, BBSphere boundingSphere)
        {
            if (points.Length < 1)
            {
                throw new ArgumentException("Your list of points must contain at least 2 points");
            }

            // Bring coordinates to ellipsoid scaled coordinates
            for (int i = 0; i < points.Length; i++)
            {
                points[i].X = points[i].X * rX;
                points[i].Y = points[i].Y * rY;
                points[i].Z = points[i].Z * rZ;
            }

            boundingSphere.Center.X = boundingSphere.Center.X * rX;
            boundingSphere.Center.Y = boundingSphere.Center.Y * rY;
            boundingSphere.Center.Z = boundingSphere.Center.Z * rZ;

            Double maxMagnitude = double.NegativeInfinity;

            for (int i = 0; i < points.Length; i++)
            {
                //magnitudes.Add(ComputeMagnitude(points[i], boundingSphere.Center));
                var magnitude = ComputeMagnitude(points[i], boundingSphere.Center);
                if (magnitude > maxMagnitude)
                {
                    maxMagnitude = magnitude;
                }
            }

            return(Cartesian3D.MultiplyByScalar(boundingSphere.Center, maxMagnitude));
        }
コード例 #2
0
        // Functions assumes ellipsoid scaled coordinates
        public static Double ComputeMagnitude(Vector3 point, Vector3 sphereCenter)
        {
            var magnitudeSquared = Cartesian3D.MagnitudeSquared(point);
            var magnitude        = Math.Sqrt(magnitudeSquared);
            var direction        = Cartesian3D.MultiplyByScalar(point, 1 / magnitude);

            magnitudeSquared = Math.Max(1.0, magnitudeSquared);
            magnitude        = Math.Max(1.0, magnitude);
            var cosAlpha = DotProduct(direction, sphereCenter);
            var sinAlpha = Cartesian3D.Magnitude(CrossProduct(direction, sphereCenter));
            var cosBeta  = 1.0 / magnitude;
            var sinBeta  = Math.Sqrt(magnitudeSquared - 1.0) * cosBeta;

            return(1.0 / (cosAlpha * cosBeta - sinAlpha * sinBeta));
        }
コード例 #3
0
        /// <summary>
        /// Encodes vertec normal into two bytes
        /// </summary>
        /// <param name="vector"></param>
        /// <returns></returns>
        public static Vector2 OctEncode(Vector3 vector)
        {
            Vector2 result     = new Vector2(0, 0);
            var     rangeMax   = 255;
            var     EPSILON6   = 0.000001;
            var     magSquared = Cartesian3D.MagnitudeSquared(vector);

            if (Math.Abs(magSquared - 1.0) > EPSILON6)
            {
                throw new ArithmeticException("vector must be normalized.");
            }
            result.X = vector.X / (Math.Abs(vector.X) + Math.Abs(vector.Y) + Math.Abs(vector.Z));
            result.Y = vector.Y / (Math.Abs(vector.X) + Math.Abs(vector.Y) + Math.Abs(vector.Z));
            if (vector.Z < 0)
            {
                var x = result.X;
                var y = result.Y;
                result.X = (1.0 - Math.Abs(y)) * SignNotZero(x);
                result.Y = (1.0 - Math.Abs(x)) * SignNotZero(y);
            }
            result.X = ToSNorm(result.X, rangeMax);
            result.Y = ToSNorm(result.Y, rangeMax);
            return(result);
        }
コード例 #4
0
        // Based on Ritter's algorithm
        public void FromPoints(Vector3[] points) // ECFC
        {
            nbPositions = points.Length;
            if (nbPositions < 2)
            {
                throw new ArgumentException("Your list of points must contain at least 2 points");
            }

            for (int i = 0; i < nbPositions; i++)
            {
                var point = points[i];
                // Store the points containing the smallest and largest component used for the naive approach
                if (point.X < minPointX.X)
                {
                    minPointX = point;
                }
                if (point.Y < minPointY.Y)
                {
                    minPointY = point;
                }
                if (point.Z < minPointZ.Z)
                {
                    minPointZ = point;
                }
                if (point.X > maxPointX.X)
                {
                    maxPointX = point;
                }
                if (point.Y > maxPointY.Y)
                {
                    maxPointY = point;
                }
                if (point.Z > maxPointZ.Z)
                {
                    maxPointZ = point;
                }
            }

            // Squared distance between each component min and max
            var xSpan     = Cartesian3D.MagnitudeSquared(Cartesian3D.Subtract(maxPointX, minPointX));
            var ySpan     = Cartesian3D.MagnitudeSquared(Cartesian3D.Subtract(maxPointY, minPointY));
            var zSpan     = Cartesian3D.MagnitudeSquared(Cartesian3D.Subtract(maxPointZ, minPointZ));
            var diameter1 = minPointX;
            var diameter2 = maxPointX;
            var maxSpan   = xSpan;

            if (ySpan > maxSpan)
            {
                maxSpan   = ySpan;
                diameter1 = minPointY;
                diameter2 = maxPointY;
            }
            if (zSpan > maxSpan)
            {
                maxSpan   = zSpan;
                diameter1 = minPointZ;
                diameter2 = maxPointZ;
            }
            var ritterCenter = new Vector3()
            {
                X = (diameter1.X + diameter2.X) * 0.5,
                Y = (diameter1.Y + diameter2.Y) * 0.5,
                Z = (diameter1.Z + diameter2.Z) * 0.5
            };

            var radiusSquared = Cartesian3D.MagnitudeSquared(Cartesian3D.Subtract(diameter2, ritterCenter));
            var ritterRadius  = Math.Sqrt(radiusSquared);
            // Initial center and radius (naive) get min and max box
            var minBoxPt = new Vector3()
            {
                X = minPointX.X,
                Y = minPointY.Y,
                Z = minPointZ.Z
            };
            var maxBoxPt = new Vector3()
            {
                X = maxPointX.X,
                Y = maxPointY.Y,
                Z = maxPointZ.Z
            };
            var naiveCenter = Cartesian3D.MultiplyByScalar(Cartesian3D.Add(minBoxPt, maxBoxPt), 0.5);
            var naiveRadius = 0.0;

            for (int i = 0; i < nbPositions; i++)
            //      foreach (var i in xrange(0, nbPositions))
            {
                var currentP = points[i];
                // Find the furthest point from the naive center to calculate the naive radius.
                var r = Cartesian3D.Magnitude(Cartesian3D.Subtract(currentP, naiveCenter));
                if (r > naiveRadius)
                {
                    naiveRadius = r;
                }
                // Make adjustments to the Ritter Sphere to include all points.
                var oldCenterToPointSquared = Cartesian3D.MagnitudeSquared(Cartesian3D.Subtract(currentP, ritterCenter));
                if (oldCenterToPointSquared > radiusSquared)
                {
                    var oldCenterToPoint = Math.Sqrt(oldCenterToPointSquared);
                    ritterRadius = (ritterRadius + oldCenterToPoint) * 0.5;
                    // Calculate center of new Ritter sphere
                    var oldToNew = oldCenterToPoint - ritterRadius;
                    ritterCenter = new Vector3()
                    {
                        X = (ritterRadius * ritterCenter.X + oldToNew * currentP.X) / oldCenterToPoint,
                        Y = (ritterRadius * ritterCenter.Y + oldToNew * currentP.Y) / oldCenterToPoint,
                        Z = (ritterRadius * ritterCenter.Z + oldToNew * currentP.Z) / oldCenterToPoint
                    };
                }
            }
            // Keep the naive sphere if smaller
            if (naiveRadius < ritterRadius)
            {
                Radius = (float)ritterRadius;
                Center = ritterCenter;
            }
            else
            {
                Radius = (float)naiveRadius;
                Center = naiveCenter;
            }
        }