Beispiel #1
0
 public void R3toS3()
 {
     for (int i = 0; i < Verts.Length; i++)
     {
         Verts[i] = Sterographic.R3toS3(Verts[i]);
     }
 }
Beispiel #2
0
        public static GreatSphere[] CalcSpheres(Sphere[] simplex, Vector3D[] poles)
        {
            HashSet <Vector3D> completedPoles = new HashSet <Vector3D>(poles, new AntipodeEqualityComparer(stereo: true));

            ReflectSpheresRecursive(simplex, completedPoles.ToArray(), completedPoles);
            return(completedPoles.Select(p => new GreatSphere(Sterographic.R3toS3(p))).ToArray());
        }
Beispiel #3
0
        public int GetHashCode(Vector3D v)
        {
            Vector3D t = m_stereo ? Sterographic.R3toS3(v) : v;

            t = new Vector3D(Math.Abs(t.X), Math.Abs(t.Y), Math.Abs(t.Z), Math.Abs(t.W));
            return(t.GetHashCode());
        }
Beispiel #4
0
        public bool Equals(Vector3D v1, Vector3D v2)
        {
            if (v1 == v2)
            {
                return(true);
            }

            Vector3D t1 = m_stereo ? Sterographic.R3toS3(v1) : v1;
            Vector3D t2 = m_stereo ? Sterographic.R3toS3(v2) : v2;

            if (t1 == t2 * -1)
            {
                return(true);
            }

            return(false);
        }
Beispiel #5
0
        public static Circle3D GeodesicFrom2Points(Vector3D a, Vector3D b)
        {
            if (a == b || a == -b)
            {
                throw new System.Exception("Geodesic not unique");
            }

            System.Func <Vector3D, Circle3D> lineFunc = p =>
            {
                Circle3D circ = new Circle3D();
                circ.Radius = double.PositiveInfinity;
                p.Normalize();
                circ.Normal = p;                    // Hacky representation of a line.
                return(circ);
            };

            if (a.IsOrigin || b.IsOrigin)
            {
                Vector3D p = a.IsOrigin ? b : a;
                return(lineFunc(p));
            }

            double mag1 = a.Abs(), mag2 = b.Abs();

            if (Tolerance.Equal(mag1, 1) && Tolerance.Equal(mag2, 1))
            {
                return(new Circle3D(a, b, a * -1));
            }

            // The antipode in S^3 of a or b will give us a 3rd point.
            Vector3D antipode = Sterographic.S3toR3(Sterographic.R3toS3(a) * -1);

            // If the antipode is also an an antipode in R3, the points are colinear
            // (or they are on the equatorial 2-sphere, but that is checked above).
            if (a == antipode * -1)
            {
                return(lineFunc(a));
            }

            return(new Circle3D(a, b, antipode));
        }
Beispiel #6
0
        private static H3.Cell.Edge[] Cull120Cell(H3.Cell.Edge[] edges)
        {
            Func <Vector3D, bool> passes = new Func <Vector3D, bool>(v =>
            {
                //return
                //	Math.Pow( v.Z, 2 ) < 0.13 &&
                //	Math.Pow( v.W, 2 ) < 0.13;
                return(Tolerance.Equal(v.W, 0.0));
            });

            H3.Cell.Edge[] result = edges.Where(e =>
            {
                Vector3D start = Sterographic.R3toS3(e.Start);
                Vector3D end   = Sterographic.R3toS3(e.End);
                return(passes(start) && passes(end));
            }).ToArray();

            // Now cull valence-2 edges.
            //result = CullValence2Edges( result );

            return(result);
        }
Beispiel #7
0
        /// <summary>
        /// Calculates our pole from a stereographically projected sphere.
        /// Assume the input sphere is a geodesic sphere in the conformal model.
        /// </summary>
        public static GreatSphere FromSphere(Sphere s)
        {
            if (s.Center.IsOrigin)
            {
                return(new GreatSphere(new Vector3D(0, 0, 0, 1)));
            }

            if (s.IsPlane)
            {
                // If we are a plane, the pole is is on the unit sphere.
                Vector3D pole = s.Normal;
                pole.Normalize();
                return(new GreatSphere(Sterographic.R3toS3(pole)));
            }

            Vector3D v1 = Sterographic.R3toS3(s.Center + new Vector3D(s.Radius, 0, 0, 0));
            Vector3D v2 = Sterographic.R3toS3(s.Center + new Vector3D(0, s.Radius, 0, 0));
            Vector3D v3 = Sterographic.R3toS3(s.Center + new Vector3D(0, 0, s.Radius, 0));

            Vector3D o = Orthogonal(v1, v2, v3);

            return(new GreatSphere(o));
        }
Beispiel #8
0
        private static void Relax(Vector3D[] coordsR3, int[] elementIndices, Vector3D[] locks)
        {
            int   dim = 4;
            Graph g   = new Graph();

            for (int i = 0; i < coordsR3.Length; i++)
            {
                Vector3D  v    = coordsR3[i];
                GraphNode node = new GraphNode(new VectorND(Sterographic.R3toS3(v)), new VectorND(dim));
                node.Lock = new VectorND(locks[i]);
                g.Nodes.Add(node);
            }

            for (int i = 0; i < elementIndices.Length; i += 3)
            {
                int a = elementIndices[i];
                int b = elementIndices[i + 1];
                int c = elementIndices[i + 2];
                g.AddEdge(new GraphEdge(a, b));
                g.AddEdge(new GraphEdge(b, c));
                g.AddEdge(new GraphEdge(c, a));
            }

            GraphRelaxation relaxer = new GraphRelaxation();

            relaxer.Graph          = g;
            relaxer.NodeRepulsion  = 0;
            relaxer.EdgeAttraction = 0.5;
            relaxer.EdgeRepulsion  = 0;
            relaxer.Relax(1000);

            for (int i = 0; i < coordsR3.Length; i++)
            {
                GraphNode node = g.Nodes[i];
                coordsR3[i] = Sterographic.S3toR3(node.Position.ToVec3D());
            }
        }
Beispiel #9
0
        private static void SpecialCase333()
        {
            /*
             *      HashSet<Vector3D> verts = new HashSet<Vector3D>();
             *      foreach( H3.Cell.Edge e in edges )
             *      {
             *              verts.Add( e.Start );
             *              verts.Add( e.End );
             *      }
             *
             *      /// We need to be smart such that the radius does not change too much at each step,
             *      /// and are going to do that by adding multiple edges.
             *      double upperTest = 35.25; // dist where rad ~300
             *
             *      System.Func<double, double> locationAtRad = rad =>
             *      {
             *              double min = 0;
             *              double max = upperTest;
             *              double current = upperTest / 2;
             *              double searchOffset = ( max - min ) / 4;
             *
             *              Vector3D cen;
             *              double radTest;
             *              H3Models.Ball.DupinCyclideSphere( verts.First() * current, .07 / 2, g, out cen, out radTest );
             *
             *              // iterate to it.
             *              double diff = Math.Abs( rad - radTest );
             *              int iterations = 1000;
             *              for( int i = 0; i < iterations; i++ )
             *              {
             *                      double t1, t2;
             *                      H3Models.Ball.DupinCyclideSphere( verts.First() * ( current + searchOffset ), .07 / 2, g, out cen, out t1 );
             *                      H3Models.Ball.DupinCyclideSphere( verts.First() * ( current - searchOffset ), .07 / 2, g, out cen, out t2 );
             *                      double d1 = Math.Abs( rad - t1 );
             *                      double d2 = Math.Abs( rad - t2 );
             *                      if( d1 == Math.Min( Math.Min( diff, d1 ), d2 ) )
             *                      {
             *                              diff = d1;
             *                              current += searchOffset;
             *                      }
             *                      if( d2 == Math.Min( Math.Min( diff, d1 ), d2 ) )
             *                      {
             *                              diff = d2;
             *                              current -= searchOffset;
             *                      }
             *
             *                      if( Tolerance.Equal( diff, 0.0, .0001 ) )
             *                              return current;
             *
             *                      searchOffset /= 2;
             *              }
             *
             *              throw new System.Exception();
             *      };
             *
             *      List<H3.Cell.Edge> toAdd = new List<H3.Cell.Edge>();
             *      foreach( Vector3D v in verts )
             *      {
             *              //toAdd.Add( new H3.Cell.Edge( v, v * 49 ) );
             *              //toAdd.Add( new H3.Cell.Edge( v * 45, v * 48.5 ) );	// need a lot of resolution here.
             *              toAdd.Add( new H3.Cell.Edge( v, v * 35.25 ) );
             *
             *              double maxRad = 300;
             *              double changePerEdge = 5;
             *              double last = 1.0;
             *              for( double rad = changePerEdge; rad < maxRad; rad += changePerEdge )
             *              {
             *                      double loc = locationAtRad( rad );
             *                      //toAdd.Add( new H3.Cell.Edge( v * last, v * loc ) );
             *                      last = loc;
             *              }
             *      }
             *      toAdd.AddRange( edges );
             *      edges = toAdd.ToArray();
             */

            // Sphere sweeps just not working - We need to add in clipped tori here.
            //Vector3D s3 = Sterographic.R3toS3( new Vector3D( 0.7 / 2, 0, 0 ) );
            Vector3D s3 = Sterographic.R3toS3(new Vector3D());

            s3 += new Vector3D();

            // r2 is major radius of torus.
            // r2 - r1 is minor radius of torus
            double   r1 = .07 / 2;
            double   r2;
            Vector3D cen;
            double   arbitrary = 0.25;

            H3Models.Ball.DupinCyclideSphere(new Vector3D(arbitrary, 0, 0), r1, Geometry.Spherical, out cen, out r2);
            double y   = cen.Abs();
            double rad = (r2 * r2 - r1 * r1 - y * y) / (2 * r1 - 2 * r2);
            double x   = rad + r1;

            System.Diagnostics.Trace.WriteLine(x);
        }
Beispiel #10
0
        private static void CompoundOfFive24Cells(ref H3.Cell.Edge[] edges)
        {
            List <H3.Cell.Edge> allEdges = new List <H3.Cell.Edge>();

            Vector3D v600 = Sterographic.R3toS3(SimplexCalcs.VertexSpherical(3, 3, 5));
            Vector3D v24  = Sterographic.R3toS3(SimplexCalcs.VertexSpherical(3, 4, 3));

            Sphere[] mirrors600 = SimplexCalcs.MirrorsSpherical(3, 3, 5);

            double a24  = v24.AngleTo(Sterographic.R3toS3(new Vector3D()));
            double a600 = v600.AngleTo(Sterographic.R3toS3(new Vector3D()));

            Matrix4D m600  = Matrix4D.MatrixToRotateinCoordinatePlane(a600, 2, 3);
            Matrix4D m600_ = Matrix4D.MatrixToRotateinCoordinatePlane(-a600, 2, 3);
            Matrix4D m24   = Matrix4D.MatrixToRotateinCoordinatePlane(a24, 2, 3);
            Matrix4D m24_  = Matrix4D.MatrixToRotateinCoordinatePlane(-a24, 2, 3);

            double eLength = 2 * Math.PI / 10;                  // 600-cell edge length
            double a_id    = Math.Asin(Math.Sin(eLength / 2) / Math.Sin(Math.PI / 3) * Math.Sin(Math.PI / 2));

            eLength = 1.0 / Math.Sin(2 * Math.PI / 5);                  // icosahedron edge length
            double a_i = Math.Asin(Math.Sin(eLength / 2) / Math.Sin(Math.PI / 3) * Math.Sin(Math.PI / 5));

            Func <Vector3D, Vector3D> rot600 = v =>
            {
                v = Sterographic.R3toS3(v);
                v = m600.RotateVector(v);
                v = Sterographic.S3toR3(v);
                return(v);
            };

            Func <Vector3D, int, Vector3D> rotOne = (v, idx) =>
            {
                v = Sterographic.R3toS3(v);
                v = m24.RotateVector(v);
                v = Sterographic.S3toR3(v);
                v.RotateAboutAxis(new Vector3D(1, 0, 0), -a_id);

                // Vertex to cell center.
                v = Sterographic.R3toS3(v);
                v = m600_.RotateVector(v);
                v = Sterographic.S3toR3(v);

                List <int> reflections = new List <int>();
                if (idx == 0)
                {
                    reflections.Add(2);
                    reflections.Add(1);
                    reflections.Add(2);
                    reflections.Add(0);
                    reflections.Add(1);
                    reflections.Add(2);
                    reflections.Add(1);
                    reflections.Add(2);
                }

                if (idx != 0)
                {
                    reflections.Add(3);
                }
                if (idx == 2)
                {
                    reflections.Add(1);
                    reflections.Add(2);
                }
                if (idx == 3)
                {
                    reflections.Add(2);
                    reflections.Add(1);
                }
                if (idx == 4)
                {
                    reflections.Add(1);
                    reflections.Add(0);
                    reflections.Add(1);
                    reflections.Add(2);
                    reflections.Add(0);
                    reflections.Add(1);
                    reflections.Add(0);
                    reflections.Add(1);
                }

                foreach (int reflection in reflections)
                {
                    v = mirrors600[reflection].ReflectPoint(v);
                }

                v = Sterographic.R3toS3(v);
                v = m600.RotateVector(v);
                v = Sterographic.S3toR3(v);

                //v.RotateAboutAxis( new Vector3D( 0, 0, 1 ), Math.PI/3 );
                //v.RotateAboutAxis( new Vector3D( 1, 0, 0 ), -a_i*2 );
                v = Sterographic.R3toS3(v);
                //v = m24_.RotateVector( v );
                v = Sterographic.S3toR3(v);


                return(v);
            };

            for (int i = 0; i < 5; i++)
            {
                //if( i == 0 )
                //	continue;

                allEdges.AddRange(edges.Select(e =>
                {
                    H3.Cell.Edge newEdge = new H3.Cell.Edge(rotOne(e.Start, i), rotOne(e.End, i));
                    //H3.Cell.Edge newEdge = new H3.Cell.Edge( rot600( e.Start ), rot600( e.End ) );
                    switch (i)
                    {
                    case 0:
                        newEdge.Color = new Vector3D(1, 0, 0, 1);
                        //newEdge.Color = new Vector3D( 1, 1, 1, 0 );
                        break;

                    case 1:
                        newEdge.Color = new Vector3D(0, 1, 0, 2);
                        break;

                    case 2:
                        newEdge.Color = new Vector3D(0, 0, 1, 3);
                        break;

                    case 3:
                        newEdge.Color = new Vector3D(1, 0, 1, 4);
                        break;

                    case 4:
                        newEdge.Color = new Vector3D(0, 1, 1, 5);
                        break;
                    }
                    return(newEdge);
                }));
            }

            edges = allEdges.ToArray();

            //edges = edges.Where( e => Tolerance.Equal( 1, e.Start.Abs() ) || Tolerance.Equal( 1, e.End.Abs() ) ).ToArray();

            HashSet <Vector3D> uniqueVerts = new HashSet <Vector3D>();

            foreach (H3.Cell.Edge e in edges)
            {
                uniqueVerts.Add(e.Start);
                uniqueVerts.Add(e.End);
            }
            System.Diagnostics.Trace.WriteLine("Number of verts = " + uniqueVerts.Count);

            /*edges = edges.Where( e =>
             * {
             *      Vector3D v = Tolerance.Equal( 1, e.Start.Abs() ) ? e.End : e.Start;
             *      if( v.Abs() >= 0.8 || v.Abs() <= 0.7 )
             *              return false;
             *
             *      if( Tolerance.LessThanOrEqual( v.X, 0 ) || Tolerance.GreaterThanOrEqual( v.Y, 0 ) || Tolerance.GreaterThanOrEqual( v.Z, 0 ) )
             *              return false;
             *
             *      return true;
             * } ).ToArray();
             *
             * edges = edges.OrderBy( e => Tolerance.Equal( 1, e.Start.Abs() ) ? e.End.Abs() : e.Start.Abs() ).ToArray();*/
        }