ReflectPoint() public method

Reflect a point in us.
public ReflectPoint ( Vector3D p ) : Vector3D
p Vector3D
return Vector3D
Beispiel #1
0
        private static void Transform(Mesh mesh)
        {
            Sphere sphere = new Sphere();

            sphere.Radius = 0.1;
            for (int i = 0; i < mesh.Triangles.Count; i++)
            {
                mesh.Triangles[i] = new Mesh.Triangle(
                    sphere.ReflectPoint(mesh.Triangles[i].a),
                    sphere.ReflectPoint(mesh.Triangles[i].b),
                    sphere.ReflectPoint(mesh.Triangles[i].c));
            }
        }
 public void Reflect(Sphere sphere)
 {
     for (int i = 0; i < 4; i++)
     {
         Verts[i] = sphere.ReflectPoint(Verts[i]);
     }
     CalcFaces();
 }
Beispiel #3
0
        /// <summary>
        /// Reflect ourselves about another sphere.
        /// </summary>
        public void Reflect(Sphere sphere)
        {
            // An interior point used to calculate whether we get inverted.
            Vector3D interiorPoint;

            if (IsPlane)
            {
                Debug.Assert(!this.Normal.IsOrigin);
                interiorPoint = this.Offset - this.Normal;
            }
            else
            {
                // We don't want it to be the center, because that will reflect to infinity.
                interiorPoint = (this.Center + new Vector3D(this.Radius / 2, 0));
            }
            if (Invert)
            {
                interiorPoint = ReflectPoint(interiorPoint);
            }
            Debug.Assert(IsPointInside(interiorPoint));
            interiorPoint = sphere.ReflectPoint(interiorPoint);
            Debug.Assert(!interiorPoint.DNE);

            if (this.Equals(sphere))
            {
                if (IsPlane)
                {
                    //this.Center = -this.Center;	// Same as inverting, but we need to do it this way because of Pov-Ray
                    this.Invert = !this.Invert;
                }
                else
                {
                    this.Invert = !this.Invert;
                }

                Debug.Assert(this.IsPointInside(interiorPoint));
                return;
            }

            // Both planes?
            if (IsPlane && sphere.IsPlane)
            {
                // XXX - not general, but I know the planes I'll be dealing with go through the origin.
                //if( !sphere.Offset.IsOrigin )
                //	throw new System.NotImplementedException();

                /*Vector3D p1 = this.Normal.Cross( sphere.Normal );
                 * if( !p1.Normalize() )
                 * {
                 *      this.Center *= -1;
                 *      return;
                 * }
                 *
                 * Vector3D p2 = p1.Cross( this.Normal );
                 * p2.Normalize();
                 * p1 = sphere.ReflectPoint( p1 );
                 * p2 = sphere.ReflectPoint( p2 );
                 * Vector3D newNormal = p2.Cross( p1 );
                 * if( !newNormal.Normalize() )
                 *      throw new System.Exception( "Reflection impl" );
                 * this.Center = newNormal;*/

                // Reflect the normal relative to the plane (conjugate with sphere.Offset).
                Vector3D newNormal = this.Normal + sphere.Offset;
                newNormal  = sphere.ReflectPoint(newNormal);
                newNormal -= sphere.Offset;
                newNormal.Normalize();
                this.Center = newNormal;

                // Calc the new offset (so far we have considered planes through origin).
                this.Offset = sphere.ReflectPoint(this.Offset);

                //Debug.Assert( Offset.IsOrigin );	// XXX - should handle more generality.
                Debug.Assert(this.IsPointInside(interiorPoint));
                return;
            }

            // We are a plane and reflecting in a sphere.
            if (IsPlane)
            {
                // Think of 2D case here (circle and line)...
                Vector3D projected = Euclidean3D.ProjectOntoPlane(this.Normal, this.Offset, sphere.Center);
                Vector3D p         = sphere.ReflectPoint(projected);
                if (Infinity.IsInfinite(p))
                {
                    // This can happen if we go through sphere.Center.
                    // This reflection does not change our orientation (does not invert us).
                    return;
                }

                Center = sphere.Center + (p - sphere.Center) / 2;
                Radius = Center.Dist(sphere.Center);

                // Did this invert us?
                if (!this.IsPointInside(interiorPoint))
                {
                    Invert = !Invert;
                }

                return;
            }

            // Is mirror a plane?
            if (sphere.IsPlane)
            {
                Vector3D projected = Euclidean3D.ProjectOntoPlane(sphere.Normal, sphere.Offset, Center);
                Vector3D diff      = Center - projected;
                Center -= 2 * diff;
                // Radius remains unchanged.
                // NOTE: This does not invert us.
                Debug.Assert(this.IsPointInside(interiorPoint));
                return;
            }

            //
            // Now sphere reflecting in a sphere.
            //

            // Reflecting to a plane?
            if (IsPointOn(sphere.Center))
            {
                // Concentric spheres?
                if (Center == sphere.Center)
                {
                    throw new System.Exception();
                }

                // Center
                Vector3D center = Center - sphere.Center;

                // Offset
                Vector3D direction = center;
                direction.Normalize();
                Vector3D offset = direction * Radius * 2;
                offset = sphere.ReflectPoint(offset);

                // We are a line now.
                Center = center;
                //Offset = offset;	// Not working??  Caused issues in old generation code for 435.
                Radius = double.PositiveInfinity;

                // Did this invert us?
                if (!this.IsPointInside(interiorPoint))
                {
                    this.Invert = !this.Invert;
                }

                Debug.Assert(this.IsPointInside(interiorPoint));
                return;
            }

            // XXX - Could try to share code below with Circle class.
            // NOTE: We can't just reflect the center.
            //		 See http://mathworld.wolfram.com/Inversion.html
            double   a = Radius;
            double   k = sphere.Radius;
            Vector3D v = Center - sphere.Center;
            double   s = k * k / (v.MagSquared() - a * a);

            Center = sphere.Center + v * s;
            Radius = Math.Abs(s) * a;

            // Did this invert us?
            if (!this.IsPointInside(interiorPoint))
            {
                Invert = !Invert;
            }
        }
Beispiel #4
0
        private static void ReflectEdgesRecursive(Sphere[] simplex, Edge[] edges, Settings settings,
                                                  HashSet <Edge> completedEdges)
        {
            if (0 == edges.Length)
            {
                return;
            }

            HashSet <Edge> newEdges = new HashSet <Edge>(new H3.Cell.EdgeEqualityComparer());

            foreach (Edge edge in edges)
            {
                //foreach( Sphere mirror in simplex )
                for (int m = 0; m < simplex.Length; m++)
                {
                    Sphere mirror = simplex[m];

                    if (completedEdges.Count > settings.MaxEdges)
                    {
                        throw new System.Exception("Maxing out edges - will result in uneven filling.");
                    }

                    Vector3D r1 = mirror.ReflectPoint(edge.Start);
                    Vector3D r2 = mirror.ReflectPoint(edge.End);

                    Edge newEdge = new Edge(r1, r2);
                    newEdge.CopyDepthsFrom(edge);
                    if (!EdgeOk(newEdge, settings))
                    {
                        continue;
                    }

                    // This tracks reflections across the cell facets.
                    newEdge.Depths[m]++;

                    // Edge color.
                    // This also controls resolution of the edges, and can have a big effect on file size.
                    // Make the threshold cutoff black, or the background color.
                    double percentWhite = 1;
                    if (settings.ThreshType == EdgeThreshType.Length)
                    {
                        percentWhite = (r1.Dist(r2) - settings.Threshold) / 0.015;
                    }
                    else
                    {
                        double closestToOrigin = Math.Min(r1.Abs(), r2.Abs());                          // Mainly ranges from 0 to 1
                        if (closestToOrigin < 0.9)
                        {
                            percentWhite = 1.0;
                        }
                        else
                        {
                            percentWhite = 1.0 - Math.Pow(closestToOrigin - 0.9, 1.3) / 0.1;
                        }
                    }
                    if (percentWhite < 0)
                    {
                        percentWhite = 0;
                    }
                    if (percentWhite > 1)
                    {
                        percentWhite = 1;
                    }
                    //newEdge.Color = new Vector3D( percentWhite, percentWhite, percentWhite );
                    newEdge.Color   = m_background;
                    newEdge.Color.Z = 0.1 + 0.9 * percentWhite;

                    if (completedEdges.Add(newEdge))
                    {
                        // Haven't seen this edge yet, so
                        // we'll need to recurse on it.
                        newEdges.Add(newEdge);
                    }
                }
            }

            ReflectEdgesRecursive(simplex, newEdges.ToArray(), settings, completedEdges);
        }
Beispiel #5
0
        /// <summary>
        /// Reflect ourselves about another sphere.
        /// </summary>
        public void Reflect( Sphere sphere )
        {
            // An interior point used to calculate whether we get inverted.
            Vector3D interiorPoint;
            if( IsPlane )
            {
                Debug.Assert( !this.Normal.IsOrigin );
                interiorPoint = -this.Normal;
            }
            else
            {
                // We don't want it to be the center, because that will reflect to infinity.
                interiorPoint = ( this.Center + new Vector3D( this.Radius / 2, 0 ) );
            }
            if( Invert )
                interiorPoint = ReflectPoint( interiorPoint );
            Debug.Assert( IsPointInside( interiorPoint ) );
            interiorPoint = sphere.ReflectPoint( interiorPoint );
            Debug.Assert( !interiorPoint.DNE );

            if( this.Equals( sphere ) )
            {
                if( IsPlane )
                {
                    //this.Center = -this.Center;	// Same as inverting, but we need to do it this way because of Pov-Ray
                    this.Invert = !this.Invert;
                }
                else
                    this.Invert = !this.Invert;

                Debug.Assert( this.IsPointInside( interiorPoint ) );
                return;
            }

            // Both planes?
            if( IsPlane && sphere.IsPlane )
            {
                // XXX - not general, but I know the planes I'll be dealing with go through the origin.
                //if( !sphere.Offset.IsOrigin )
                //	throw new System.NotImplementedException();

                /*Vector3D p1 = this.Normal.Cross( sphere.Normal );
                if( !p1.Normalize() )
                {
                    this.Center *= -1;
                    return;
                }

                Vector3D p2 = p1.Cross( this.Normal );
                p2.Normalize();
                p1 = sphere.ReflectPoint( p1 );
                p2 = sphere.ReflectPoint( p2 );
                Vector3D newNormal = p2.Cross( p1 );
                if( !newNormal.Normalize() )
                    throw new System.Exception( "Reflection impl" );
                this.Center = newNormal;*/

                // Reflect the normal relative to the plane (conjugate with sphere.Offset).
                Vector3D newNormal = this.Normal + sphere.Offset;
                newNormal = sphere.ReflectPoint( newNormal );
                newNormal -= sphere.Offset;
                newNormal.Normalize();
                this.Center = newNormal;

                // Calc the new offset (so far we have considered planes through origin).
                this.Offset = sphere.ReflectPoint( this.Offset );

                //Debug.Assert( Offset.IsOrigin );	// XXX - should handle more generality.
                Debug.Assert( this.IsPointInside( interiorPoint ) );
                return;
            }

            // We are a plane and reflecting in a sphere.
            if( IsPlane )
            {
                // Think of 2D case here (circle and line)...
                Vector3D projected  = Euclidean3D.ProjectOntoPlane( this.Normal, this.Offset, sphere.Center );
                Vector3D p = sphere.ReflectPoint( projected );
                if( Infinity.IsInfinite( p ) )
                {
                    // This can happen if we go through sphere.Center.
                    // This reflection does not change our orientation (does not invert us).
                    return;
                }

                Center = sphere.Center + ( p - sphere.Center ) / 2;
                Radius = Center.Dist( sphere.Center );

                // Did this invert us?
                if( !this.IsPointInside( interiorPoint ) )
                    Invert = !Invert;

                return;
            }

            // Is mirror a plane?
            if( sphere.IsPlane )
            {
                Vector3D projected = Euclidean3D.ProjectOntoPlane( sphere.Normal, sphere.Offset, Center );
                Vector3D diff = Center - projected;
                Center -= 2 * diff;
                // Radius remains unchanged.
                // NOTE: This does not invert us.
                Debug.Assert( this.IsPointInside( interiorPoint ) );
                return;
            }

            //
            // Now sphere reflecting in a sphere.
            //

            // Reflecting to a plane?
            if( IsPointOn( sphere.Center ) )
            {
                // Concentric spheres?
                if( Center == sphere.Center )
                    throw new System.Exception();

                // Center
                Vector3D center = Center - sphere.Center;

                // Offset
                Vector3D direction = center;
                direction.Normalize();
                Vector3D offset = direction * Radius * 2;
                offset = sphere.ReflectPoint( offset );

                // We are a line now.
                Center = center;
                //Offset = offset;	// Not working??  Caused issues in old generation code for 435.
                Radius = double.PositiveInfinity;

                // Did this invert us?
                if( !this.IsPointInside( interiorPoint ) )
                    this.Invert = !this.Invert;

                Debug.Assert( this.IsPointInside( interiorPoint ) );
                return;
            }

            // XXX - Could try to share code below with Circle class.
            // NOTE: We can't just reflect the center.
            //		 See http://mathworld.wolfram.com/Inversion.html
            double a = Radius;
            double k = sphere.Radius;
            Vector3D v = Center - sphere.Center;
            double s = k * k / ( v.MagSquared() - a * a );
            Center = sphere.Center + v * s;
            Radius = Math.Abs( s ) * a;

            // Did this invert us?
            if( !this.IsPointInside( interiorPoint ) )
                Invert = !Invert;
        }
Beispiel #6
0
            /// <summary>
            /// Given 2 points in the interior of the ball, calculate the center and radius of the orthogonal circle.
            /// One point may optionally be on the boundary, but one shoudl be in the interior.
            /// If both points are on the boundary, we'll fall back on our other method.
            /// </summary>
            public static void OrthogonalCircleInterior( Vector3D v1, Vector3D v2, out Circle3D circle )
            {
                if( Tolerance.Equal( v1.Abs(), 1 ) &&
                    Tolerance.Equal( v2.Abs(), 1 ) )
                {
                    circle = OrthogonalCircle( v1, v2 );
                    return;
                }

                // http://www.math.washington.edu/~king/coursedir/m445w06/ortho/01-07-ortho-to3.html
                // http://www.youtube.com/watch?v=Bkvo09KE1zo

                Vector3D interior = Tolerance.Equal( v1.Abs(), 1 ) ? v2 : v1;

                Sphere ball = new Sphere();
                Vector3D reflected = ball.ReflectPoint( interior );
                circle = new Circle3D( reflected, v1, v2 );
            }
Beispiel #7
0
        /// <summary>
        /// Using this to move the view around in interesting ways.
        /// </summary>
        private Vector3D ApplyTransformation( Vector3D v, double t = 0.0 )
        {
            //v.RotateXY( Math.PI / 4 + 0.01 );
            bool applyNone = true;
            if( applyNone )
                return v;

            Mobius m0 = new Mobius(), m1 = new Mobius(), m2 = new Mobius(), m3 = new Mobius();
            Sphere unitSphere = new Sphere();

            // self-similar scale for 437
            //v*= 4.259171776329806;

            double s = 6.5;
            v *= s;
            v += new Vector3D( s/3, -s/3 );
            v = unitSphere.ReflectPoint( v );
            v.RotateXY( Math.PI/6 );
            //v /= 3;
            //v.RotateXY( Math.PI );
            //v.RotateXY( Math.PI/2 );
            return v;

            //v.Y = v.Y / Math.Cos( Math.PI / 6 );	// 637 repeatable
            //return v;

            // 12,12,12
            m0.Isometry( Geometry.Hyperbolic, 0, new Complex( .0, .0 ) );
            m1 = Mobius.Identity();
            m2 = Mobius.Identity();
            m3 = Mobius.Identity();
            v = (m0 * m1 * m2 * m3).Apply( v );
            return v;

            // i64
            m0.Isometry( Geometry.Hyperbolic, 0, new Complex( .5, .5 ) );
            m1.UpperHalfPlane();
            m2 = Mobius.Scale( 1.333333 );
            m3.Isometry( Geometry.Euclidean, 0, new Vector3D( 0, -1.1 ) );
            v = (m1 * m2 * m3).Apply( v );
            return v;

            // 464
            // NOTE: Also, don't apply rotations during simplex generation.
            m1.UpperHalfPlane();
            m2 = Mobius.Scale( 1.3 );
            m3.Isometry( Geometry.Euclidean, 0, new Vector3D( 1.55, -1.1 ) );
            v = ( m1 * m2 * m3 ).Apply( v );
            return v;

            // iii
            m1.Isometry( Geometry.Hyperbolic, 0, new Complex( 0, Math.Sqrt( 2 ) - 1 ) );
            m2.Isometry( Geometry.Euclidean, -Math.PI / 4, 0 );
            m3 = Mobius.Scale( 5 );
            //v = ( m1 * m2 * m3 ).Apply( v );

            // Vertical Line
            /*v = unitSphere.ReflectPoint( v );
            m1.MapPoints( new Vector3D(-1,0), new Vector3D(), new Vector3D( 1, 0 ) );
            m2 = Mobius.Scale( .5 );
            v = (m1*m2).Apply( v ); */

            /*
            m1 = Mobius.Scale( 0.175 );
            v = unitSphere.ReflectPoint( v );
            v = m1.Apply( v );
             * */

            // Inversion
            //v = unitSphere.ReflectPoint( v );
            //return v;

            /*Mobius m1 = new Mobius(), m2 = new Mobius(), m3 = new Mobius();
            m1.Isometry( Geometry.Spherical, 0, new Complex( 0, 1 ) );
            m2.Isometry( Geometry.Euclidean, 0, new Complex( 0, -1 ) );
            m3 = Mobius.Scale( 0.5 );
            v = (m1 * m3 * m2).Apply( v );*/

            //Mobius m = new Mobius();
            //m.Isometry( Geometry.Hyperbolic, 0, new Complex( -0.88, 0 ) );
            //m.Isometry( Geometry.Hyperbolic, 0, new Complex( 0, Math.Sqrt(2) - 1 ) );
            //m = Mobius.Scale( 0.17 );
            //m.Isometry( Geometry.Spherical, 0, new Complex( 0, 3.0 ) );
            //v = m.Apply( v );

            // 63i, 73i
            m1 = Mobius.Scale( 6.0 ); // Scale {3,i} to unit disk.
            m1 = Mobius.Scale( 1.0 / 0.14062592996431983 ); // 73i	(constant is abs of midpoint of {3,7} tiling, if we want to calc later for other tilings).
            m2.MapPoints( Infinity.InfinityVector, new Vector3D( 1, 0 ), new Vector3D() ); // swap interior/exterior
            m3.UpperHalfPlane();
            v *= 2.9;

            // iii
            /*m1.MapPoints( new Vector3D(), new Vector3D(1,0), new Vector3D( Math.Sqrt( 2 ) - 1, 0 ) );
            m2.Isometry( Geometry.Euclidean, -Math.PI / 4, 0 );
            m3 = Mobius.Scale( 0.75 );*/

            Mobius m = m3 * m2 * m1;
            v = m.Inverse().Apply( v );	// Strange that we have to do inverse here.

            return v;
        }