Beispiel #1
0
        private void Update(Context context)
        {
            if (_dirtyLength)
            {
                VertexAttributeDoubleVector3 positionAttribute = new VertexAttributeDoubleVector3("position", 6);
                positionAttribute.Values.Add(new Vector3D(0, 0, 0));
                positionAttribute.Values.Add(new Vector3D(_length, 0, 0));
                positionAttribute.Values.Add(new Vector3D(0, 0, 0));
                positionAttribute.Values.Add(new Vector3D(0, _length, 0));
                positionAttribute.Values.Add(new Vector3D(0, 0, 0));
                positionAttribute.Values.Add(new Vector3D(0, 0, _length));

                VertexAttributeRGBA colorAttribute = new VertexAttributeRGBA("color", 6);
                colorAttribute.AddColor(Color.Red);
                colorAttribute.AddColor(Color.Red);
                colorAttribute.AddColor(Color.Green);
                colorAttribute.AddColor(Color.Green);
                colorAttribute.AddColor(Color.Blue);
                colorAttribute.AddColor(Color.Blue);

                Mesh mesh = new Mesh();
                mesh.PrimitiveType = PrimitiveType.Lines;
                mesh.Attributes.Add(positionAttribute);
                mesh.Attributes.Add(colorAttribute);

                _polyline.Set(context, mesh);

                _dirtyLength = false;
            }

            _polyline.Width = Width;
        }
Beispiel #2
0
        private void Update(Context context)
        {
            if (_dirtyLength)
            {
                VertexAttributeDoubleVector3 positionAttribute = new VertexAttributeDoubleVector3("position", 6);
                positionAttribute.Values.Add(new Vector3D(0, 0, 0));
                positionAttribute.Values.Add(new Vector3D(_length, 0, 0));
                positionAttribute.Values.Add(new Vector3D(0, 0, 0));
                positionAttribute.Values.Add(new Vector3D(0, _length, 0));
                positionAttribute.Values.Add(new Vector3D(0, 0, 0));
                positionAttribute.Values.Add(new Vector3D(0, 0, _length));

                VertexAttributeRGBA colorAttribute = new VertexAttributeRGBA("color", 6);
                colorAttribute.AddColor(Color.Red);
                colorAttribute.AddColor(Color.Red);
                colorAttribute.AddColor(Color.Green);
                colorAttribute.AddColor(Color.Green);
                colorAttribute.AddColor(Color.Blue);
                colorAttribute.AddColor(Color.Blue);

                Mesh mesh = new Mesh();
                mesh.PrimitiveType = PrimitiveType.Lines;
                mesh.Attributes.Add(positionAttribute);
                mesh.Attributes.Add(colorAttribute);

                _polyline.Set(context, mesh);

                _dirtyLength = false;
            }

            _polyline.Width = Width;
        }
Beispiel #3
0
        public PolygonShapefile(
            Shapefile shapefile,
            Context context,
            Ellipsoid globeShape,
            ShapefileAppearance appearance)
        {
            Verify.ThrowIfNull(shapefile);
            Verify.ThrowIfNull(context);
            Verify.ThrowIfNull(globeShape);

            _polyline = new OutlinedPolylineTexture();
            _polygons = new List <Polygon>();

            VertexAttributeDoubleVector3 positionAttribute     = new VertexAttributeDoubleVector3("position");
            VertexAttributeRGBA          colorAttribute        = new VertexAttributeRGBA("color");
            VertexAttributeRGBA          outlineColorAttribute = new VertexAttributeRGBA("outlineColor");
            IndicesUnsignedInt           indices = new IndicesUnsignedInt();

            Random           r         = new Random(3);
            IList <Vector3D> positions = new List <Vector3D>();

            foreach (Shape shape in shapefile)
            {
                if (shape.ShapeType != ShapeType.Polygon)
                {
                    throw new NotSupportedException("The type of an individual shape does not match the Shapefile type.");
                }

                PolygonShape polygonShape = (PolygonShape)shape;

                for (int j = 0; j < polygonShape.Count; ++j)
                {
                    Color color = Color.FromArgb(127, r.Next(256), r.Next(256), r.Next(256));

                    positions.Clear();

                    ShapePart part = polygonShape[j];

                    for (int i = 0; i < part.Count; ++i)
                    {
                        Vector2D point = part[i];

                        positions.Add(globeShape.ToVector3D(Trig.ToRadians(new Geodetic3D(point.X, point.Y))));

                        //
                        // For polyline
                        //
                        positionAttribute.Values.Add(globeShape.ToVector3D(Trig.ToRadians(new Geodetic3D(point.X, point.Y))));
                        colorAttribute.AddColor(color);
                        outlineColorAttribute.AddColor(Color.Black);

                        if (i != 0)
                        {
                            indices.Values.Add((uint)positionAttribute.Values.Count - 2);
                            indices.Values.Add((uint)positionAttribute.Values.Count - 1);
                        }
                    }

                    try
                    {
                        Polygon p = new Polygon(context, globeShape, positions);
                        p.Color = color;
                        _polygons.Add(p);
                    }
                    catch (ArgumentOutOfRangeException) // Not enough positions after cleaning
                    {
                    }
                }
            }

            Mesh mesh = new Mesh();

            mesh.PrimitiveType = PrimitiveType.Lines;
            mesh.Attributes.Add(positionAttribute);
            mesh.Attributes.Add(colorAttribute);
            mesh.Attributes.Add(outlineColorAttribute);
            mesh.Indices = indices;
            _polyline.Set(context, mesh);
        }
Beispiel #4
0
        public void MeshVertexAttributes()
        {
            Mesh mesh = new Mesh();

            VertexAttributeHalfFloat halfFloatAttribute = new VertexAttributeHalfFloat("halfFloatAttribute");
            mesh.Attributes.Add(halfFloatAttribute);
            Assert.AreEqual("halfFloatAttribute", mesh.Attributes["halfFloatAttribute"].Name);
            Assert.AreEqual(VertexAttributeType.HalfFloat, mesh.Attributes["halfFloatAttribute"].Datatype);

            VertexAttributeHalfFloatVector2 halfFloatAttribute2 = new VertexAttributeHalfFloatVector2("halfFloatAttribute2");
            mesh.Attributes.Add(halfFloatAttribute2);
            Assert.AreEqual("halfFloatAttribute2", mesh.Attributes["halfFloatAttribute2"].Name);
            Assert.AreEqual(VertexAttributeType.HalfFloatVector2, mesh.Attributes["halfFloatAttribute2"].Datatype);

            VertexAttributeHalfFloatVector3 halfFloatAttribute3 = new VertexAttributeHalfFloatVector3("halfFloatAttribute3");
            mesh.Attributes.Add(halfFloatAttribute3);
            Assert.AreEqual("halfFloatAttribute3", mesh.Attributes["halfFloatAttribute3"].Name);
            Assert.AreEqual(VertexAttributeType.HalfFloatVector3, mesh.Attributes["halfFloatAttribute3"].Datatype);

            VertexAttributeHalfFloatVector4 halfFloatAttribute4 = new VertexAttributeHalfFloatVector4("halfFloatAttribute4");
            mesh.Attributes.Add(halfFloatAttribute4);
            Assert.AreEqual("halfFloatAttribute4", mesh.Attributes["halfFloatAttribute4"].Name);
            Assert.AreEqual(VertexAttributeType.HalfFloatVector4, mesh.Attributes["halfFloatAttribute4"].Datatype);

            ///////////////////////////////////////////////////////////////////

            VertexAttributeFloat floatAttribute = new VertexAttributeFloat("floatAttribute");
            mesh.Attributes.Add(floatAttribute);
            Assert.AreEqual("floatAttribute", mesh.Attributes["floatAttribute"].Name);
            Assert.AreEqual(VertexAttributeType.Float, mesh.Attributes["floatAttribute"].Datatype);

            VertexAttributeFloatVector2 floatAttribute2 = new VertexAttributeFloatVector2("floatAttribute2");
            mesh.Attributes.Add(floatAttribute2);
            Assert.AreEqual("floatAttribute2", mesh.Attributes["floatAttribute2"].Name);
            Assert.AreEqual(VertexAttributeType.FloatVector2, mesh.Attributes["floatAttribute2"].Datatype);

            VertexAttributeFloatVector3 floatAttribute3 = new VertexAttributeFloatVector3("floatAttribute3");
            mesh.Attributes.Add(floatAttribute3);
            Assert.AreEqual("floatAttribute3", mesh.Attributes["floatAttribute3"].Name);
            Assert.AreEqual(VertexAttributeType.FloatVector3, mesh.Attributes["floatAttribute3"].Datatype);

            VertexAttributeFloatVector4 floatAttribute4 = new VertexAttributeFloatVector4("floatAttribute4");
            mesh.Attributes.Add(floatAttribute4);
            Assert.AreEqual("floatAttribute4", mesh.Attributes["floatAttribute4"].Name);
            Assert.AreEqual(VertexAttributeType.FloatVector4, mesh.Attributes["floatAttribute4"].Datatype);

            ///////////////////////////////////////////////////////////////////

            VertexAttributeByte byteAttribute = new VertexAttributeByte("byteAttribute");
            mesh.Attributes.Add(byteAttribute);
            Assert.AreEqual("byteAttribute", mesh.Attributes["byteAttribute"].Name);
            Assert.AreEqual(VertexAttributeType.UnsignedByte, mesh.Attributes["byteAttribute"].Datatype);

            VertexAttributeRGBA colorAttribute = new VertexAttributeRGBA("colorAttribute");
            mesh.Attributes.Add(colorAttribute);
            Assert.AreEqual("colorAttribute", mesh.Attributes["colorAttribute"].Name);
            Assert.AreEqual(VertexAttributeType.UnsignedByte, mesh.Attributes["colorAttribute"].Datatype);

            colorAttribute.AddColor(Color.FromArgb(3, 0, 1, 2));
            Assert.AreEqual(0, colorAttribute.Values[0]);
            Assert.AreEqual(1, colorAttribute.Values[1]);
            Assert.AreEqual(2, colorAttribute.Values[2]);
            Assert.AreEqual(3, colorAttribute.Values[3]);
        }
Beispiel #5
0
        private void CreateScene()
        {
            // 设置窗口表面指令信息显示内容
            string text = "Granularity: " + _granularityInDegrees + " (left/right)\n";

            text += "Points: " + (_sampledPoints.Show ? "on" : "off") + " ('1')\n";
            text += "Polyline: " + (_polyline.Show ? "on" : "off") + " ('2')\n";
            text += "Plane: " + (_plane.Show ? "on" : "off") + " ('3')\n";
            text += "Semi-minor axis (up/down)\n";

            // 转换指令信息文字内容为图像纹理
            _instructions.Texture = Device.CreateTexture2D(
                Device.CreateBitmapFromText(text, new Font("Arial", 24)),
                TextureFormat.RedGreenBlueAlpha8, false);

            ///////////////////////////////////////////////////////////////////

            // 基于椭球形状计算表面采样点三维坐标
            IList <Vector3D> positions = _globeShape.ComputeCurve(
                _p, _q, Trig.ToRadians(_granularityInDegrees));

            // 设置椭球表面采样点billboard集合的位置和颜色
            _sampledPoints.Clear();
            _sampledPoints.Add(new Billboard()
            {
                Position = positions[0], Color = Color.Orange
            });
            _sampledPoints.Add(new Billboard()
            {
                Position = positions[positions.Count - 1], Color = Color.Orange
            });

            for (int i = 1; i < positions.Count - 1; ++i)
            {
                _sampledPoints.Add(new Billboard()
                {
                    Position = positions[i],
                    Color    = Color.Yellow
                });
            }

            ///////////////////////////////////////////////////////////////////

            // 设置椭球的尺寸形状信息
            _ellipsoid.Shape = _globeShape;

            ///////////////////////////////////////////////////////////////////

            // 计算椭球表面曲线位置和颜色
            VertexAttributeFloatVector3 positionAttribute = new VertexAttributeFloatVector3("position", positions.Count);
            VertexAttributeRGBA         colorAttribute    = new VertexAttributeRGBA("color", positions.Count);

            for (int i = 0; i < positions.Count; ++i)
            {
                positionAttribute.Values.Add(positions[i].ToVector3F());
                colorAttribute.AddColor(Color.Red);
            }

            // 创建椭球表面曲线
            Mesh mesh = new Mesh();

            mesh.PrimitiveType = PrimitiveType.LineStrip;
            mesh.Attributes.Add(positionAttribute);
            mesh.Attributes.Add(colorAttribute);

            _polyline.Set(_window.Context, mesh);

            ///////////////////////////////////////////////////////////////////

            // 设置显示参考面缩放使其略大于椭球
            double scale = 1.25 * _globeShape.Radii.MaximumComponent;

            // 设置参考面X轴穿过p点
            _plane.XAxis = scale * _p.Normalize();
            _plane.YAxis = scale * _p.Cross(_q).Cross(_p).Normalize();
        }
        public PolylineShapefile(
            Shapefile shapefile,
            Context context,
            Ellipsoid globeShape,
            ShapefileAppearance appearance)
        {
            Verify.ThrowIfNull(shapefile);
            Verify.ThrowIfNull(context);
            Verify.ThrowIfNull(globeShape);
            Verify.ThrowIfNull(appearance);

            _polyline = new OutlinedPolylineTexture();

            int positionsCount = 0;
            int indicesCount   = 0;

            PolylineCapacities(shapefile, out positionsCount, out indicesCount);

            VertexAttributeDoubleVector3 positionAttribute     = new VertexAttributeDoubleVector3("position", positionsCount);
            VertexAttributeRGBA          colorAttribute        = new VertexAttributeRGBA("color", positionsCount);
            VertexAttributeRGBA          outlineColorAttribute = new VertexAttributeRGBA("outlineColor", positionsCount);
            IndicesUnsignedInt           indices = new IndicesUnsignedInt(indicesCount);

            foreach (Shape shape in shapefile)
            {
                if (shape.ShapeType != ShapeType.Polyline)
                {
                    throw new NotSupportedException("The type of an individual shape does not match the Shapefile type.");
                }

                PolylineShape polylineShape = (PolylineShape)shape;

                for (int j = 0; j < polylineShape.Count; ++j)
                {
                    ShapePart part = polylineShape[j];

                    for (int i = 0; i < part.Count; ++i)
                    {
                        Vector2D point = part[i];

                        positionAttribute.Values.Add(globeShape.ToVector3D(Trig.ToRadians(new Geodetic3D(point.X, point.Y))));
                        colorAttribute.AddColor(appearance.PolylineColor);
                        outlineColorAttribute.AddColor(appearance.PolylineOutlineColor);

                        if (i != 0)
                        {
                            indices.Values.Add((uint)positionAttribute.Values.Count - 2);
                            indices.Values.Add((uint)positionAttribute.Values.Count - 1);
                        }
                    }
                }
            }

            Mesh mesh = new Mesh();

            mesh.PrimitiveType = PrimitiveType.Lines;
            mesh.Attributes.Add(positionAttribute);
            mesh.Attributes.Add(colorAttribute);
            mesh.Attributes.Add(outlineColorAttribute);
            mesh.Indices = indices;
            _polyline.Set(context, mesh);
            _polyline.Width        = appearance.PolylineWidth;
            _polyline.OutlineWidth = appearance.PolylineOutlineWidth;
        }
        public PolygonShapefile(
            Shapefile shapefile, 
            Context context, 
            Ellipsoid globeShape,
            ShapefileAppearance appearance)
        {
            Verify.ThrowIfNull(shapefile);
            Verify.ThrowIfNull(context);
            Verify.ThrowIfNull(globeShape);

            _polyline = new OutlinedPolylineTexture();
            _polygons = new List<Polygon>();

            VertexAttributeDoubleVector3 positionAttribute = new VertexAttributeDoubleVector3("position");
            VertexAttributeRGBA colorAttribute = new VertexAttributeRGBA("color");
            VertexAttributeRGBA outlineColorAttribute = new VertexAttributeRGBA("outlineColor");
            IndicesUnsignedInt indices = new IndicesUnsignedInt();

            Random r = new Random(3);
            IList<Vector3D> positions = new List<Vector3D>();

            foreach (Shape shape in shapefile)
            {
                if (shape.ShapeType != ShapeType.Polygon)
                {
                    throw new NotSupportedException("The type of an individual shape does not match the Shapefile type.");
                }

                PolygonShape polygonShape = (PolygonShape)shape;

                for (int j = 0; j < polygonShape.Count; ++j)
                {
                    Color color = Color.FromArgb(127, r.Next(256), r.Next(256), r.Next(256));

                    positions.Clear();

                    ShapePart part = polygonShape[j];

                    for (int i = 0; i < part.Count; ++i)
                    {
                        Vector2D point = part[i];

                        positions.Add(globeShape.ToVector3D(Trig.ToRadians(new Geodetic3D(point.X, point.Y))));

                        //
                        // For polyline
                        //
                        positionAttribute.Values.Add(globeShape.ToVector3D(Trig.ToRadians(new Geodetic3D(point.X, point.Y))));
                        colorAttribute.AddColor(color);
                        outlineColorAttribute.AddColor(Color.Black);

                        if (i != 0)
                        {
                            indices.Values.Add((uint)positionAttribute.Values.Count - 2);
                            indices.Values.Add((uint)positionAttribute.Values.Count - 1);
                        }
                    }

                    try
                    {
                        Polygon p = new Polygon(context, globeShape, positions);
                        p.Color = color;
                        _polygons.Add(p);
                    }
                    catch (ArgumentOutOfRangeException) // Not enough positions after cleaning
                    {
                    }
                }
            }

            Mesh mesh = new Mesh();
            mesh.PrimitiveType = PrimitiveType.Lines;
            mesh.Attributes.Add(positionAttribute);
            mesh.Attributes.Add(colorAttribute);
            mesh.Attributes.Add(outlineColorAttribute);
            mesh.Indices = indices;
            _polyline.Set(context, mesh);
        }
        public PolylineShapefile(
            Shapefile shapefile, 
            Context context, 
            Ellipsoid globeShape, 
            ShapefileAppearance appearance)
        {
            Verify.ThrowIfNull(shapefile);
            Verify.ThrowIfNull(context);
            Verify.ThrowIfNull(globeShape);
            Verify.ThrowIfNull(appearance);
            
            _polyline = new OutlinedPolylineTexture();

            int positionsCount = 0;
            int indicesCount = 0;
            PolylineCapacities(shapefile, out positionsCount, out indicesCount);

            VertexAttributeDoubleVector3 positionAttribute = new VertexAttributeDoubleVector3("position", positionsCount);
            VertexAttributeRGBA colorAttribute = new VertexAttributeRGBA("color", positionsCount);
            VertexAttributeRGBA outlineColorAttribute = new VertexAttributeRGBA("outlineColor", positionsCount);
            IndicesUnsignedInt indices = new IndicesUnsignedInt(indicesCount);

            foreach (Shape shape in shapefile)
            {
                if (shape.ShapeType != ShapeType.Polyline)
                {
                    throw new NotSupportedException("The type of an individual shape does not match the Shapefile type.");
                }

                PolylineShape polylineShape = (PolylineShape)shape;

                for (int j = 0; j < polylineShape.Count; ++j)
                {
                    ShapePart part = polylineShape[j];

                    for (int i = 0; i < part.Count; ++i)
                    {
                        Vector2D point = part[i];

                        positionAttribute.Values.Add(globeShape.ToVector3D(Trig.ToRadians(new Geodetic3D(point.X, point.Y))));
                        colorAttribute.AddColor(appearance.PolylineColor);
                        outlineColorAttribute.AddColor(appearance.PolylineOutlineColor);

                        if (i != 0)
                        {
                            indices.Values.Add((uint)positionAttribute.Values.Count - 2);
                            indices.Values.Add((uint)positionAttribute.Values.Count - 1);
                        }
                    }
                }
            }

            Mesh mesh = new Mesh();
            mesh.PrimitiveType = PrimitiveType.Lines;
            mesh.Attributes.Add(positionAttribute);
            mesh.Attributes.Add(colorAttribute);
            mesh.Attributes.Add(outlineColorAttribute);
            mesh.Indices = indices;
            _polyline.Set(context, mesh);
            _polyline.Width = appearance.PolylineWidth;
            _polyline.OutlineWidth = appearance.PolylineOutlineWidth;
        }
Beispiel #9
0
        private void CreateScene()
        {
            DisposeScene();

            _ellipsoid       = new TessellatedGlobe();
            _ellipsoid.Shape = _globeShape;
            _ellipsoid.NumberOfSlicePartitions = 64;
            _ellipsoid.NumberOfStackPartitions = 32;

            ///////////////////////////////////////////////////////////////////

            // 计算椭球网格
            Mesh mesh = GeographicGridEllipsoidTessellator.Compute(_globeShape,
                                                                   64, 32, GeographicGridEllipsoidVertexAttributes.Position);

            // 创建椭球网格线框显示对象
            _wireframe       = new Wireframe(_window.Context, mesh);
            _wireframe.Width = 2;

            ///////////////////////////////////////////////////////////////////

            // 创建坐标轴显示对象
            _axes        = new Axes();
            _axes.Length = 1.5;
            _axes.Width  = 3;

            ///////////////////////////////////////////////////////////////////

            // 计算p点椭球表面坐标
            Vector3D p = _globeShape.ToVector3D(new Geodetic3D(0, Trig.ToRadians(45), 0));
            // 计算p点地理法线向量
            Vector3D deticNormal = _globeShape.GeodeticSurfaceNormal(p);
            // 计算p点地心法线向量
            Vector3D centricNormal = Ellipsoid.CentricSurfaceNormal(p);

            double normalLength = _globeShape.MaximumRadius;
            // 计算地理法线末端点三维坐标
            Vector3D pDetic   = p + (normalLength * deticNormal);
            Vector3D pCentric = p + (normalLength * centricNormal);

            VertexAttributeFloatVector3 positionAttribute = new VertexAttributeFloatVector3("position", 4);

            // 创建地理法线段顶点
            positionAttribute.Values.Add(p.ToVector3F());
            positionAttribute.Values.Add(pDetic.ToVector3F());
            // 创建地心法线段顶点
            positionAttribute.Values.Add(p.ToVector3F());
            positionAttribute.Values.Add(pCentric.ToVector3F());

            VertexAttributeRGBA colorAttribute = new VertexAttributeRGBA("color", 4);

            // 创建地理法线段顶点颜色
            colorAttribute.AddColor(Color.DarkGreen);
            colorAttribute.AddColor(Color.DarkGreen);
            // 创建地心法线段顶点颜色
            colorAttribute.AddColor(Color.DarkCyan);
            colorAttribute.AddColor(Color.DarkCyan);

            // 创建地理/地心发现段图形显示元语
            Mesh polyline = new Mesh();

            polyline.PrimitiveType = PrimitiveType.Lines;
            polyline.Attributes.Add(positionAttribute);
            polyline.Attributes.Add(colorAttribute);

            _normals = new Polyline();
            _normals.Set(_window.Context, polyline);
            _normals.Width = 3;

            ///////////////////////////////////////////////////////////////////
            Font           font         = new Font("Arial", 24);
            IList <Bitmap> labelBitmaps = new List <Bitmap>(2);

            labelBitmaps.Add(Device.CreateBitmapFromText("Geodetic", font));
            labelBitmaps.Add(Device.CreateBitmapFromText("Geocentric", font));
            font.Dispose();

            // 创建纹理压缩对象?
            TextureAtlas atlas = new TextureAtlas(labelBitmaps);

            _labels         = new BillboardCollection(_window.Context, 2);
            _labels.Texture = Device.CreateTexture2D(atlas.Bitmap, TextureFormat.RedGreenBlueAlpha8, false);
            _labels.Add(new Billboard()
            {
                Position = pDetic,
                // 取第一个纹理
                TextureCoordinates = atlas.TextureCoordinates[0],
                Color            = Color.DarkGreen,
                HorizontalOrigin = HorizontalOrigin.Right,
                VerticalOrigin   = VerticalOrigin.Bottom
            });
            _labels.Add(new Billboard()
            {
                Position = pCentric,
                // 取第二个纹理
                TextureCoordinates = atlas.TextureCoordinates[1],
                Color            = Color.DarkCyan,
                HorizontalOrigin = HorizontalOrigin.Right,
                VerticalOrigin   = VerticalOrigin.Bottom
            });

            atlas.Dispose();

            ///////////////////////////////////////////////////////////////////
            Vector3D east  = Vector3D.UnitZ.Cross(deticNormal);
            Vector3D north = deticNormal.Cross(east);

            // 创建p点切平面
            _tangentPlane              = new Plane(_window.Context);
            _tangentPlane.Origin       = p;
            _tangentPlane.XAxis        = east;
            _tangentPlane.YAxis        = north;
            _tangentPlane.OutlineWidth = 3;
        }
Beispiel #10
0
        private void CreateScene()
        {
            string text = "Granularity: " + _granularityInDegrees + " (left/right)\n";
            text += "Points: " + (_sampledPoints.Show ? "on" : "off") + " ('1')\n";
            text += "Polyline: " + (_polyline.Show ? "on" : "off") + " ('2')\n";
            text += "Plane: " + (_plane.Show ? "on" : "off") + " ('3')\n";
            text += "Semi-minor axis (up/down)\n";

            _instructions.Texture = Device.CreateTexture2D(
                Device.CreateBitmapFromText(text, new Font("Arial", 24)),
                TextureFormat.RedGreenBlueAlpha8, false);

            ///////////////////////////////////////////////////////////////////

            IList<Vector3D> positions = _globeShape.ComputeCurve(
                _p, _q, Trig.ToRadians(_granularityInDegrees));

            _sampledPoints.Clear();
            _sampledPoints.Add(new Billboard() { Position = positions[0], Color = Color.Orange });
            _sampledPoints.Add(new Billboard() { Position = positions[positions.Count - 1], Color = Color.Orange });

            for (int i = 1; i < positions.Count - 1; ++i)
            {
                _sampledPoints.Add(new Billboard() 
                { 
                    Position = positions[i], 
                    Color = Color.Yellow 
                });
            }

            ///////////////////////////////////////////////////////////////////

            _ellipsoid.Shape = _globeShape;

            ///////////////////////////////////////////////////////////////////
            
            VertexAttributeFloatVector3 positionAttribute = new VertexAttributeFloatVector3("position", positions.Count);
            VertexAttributeRGBA colorAttribute = new VertexAttributeRGBA("color", positions.Count);

            for (int i = 0; i < positions.Count; ++i)
            {
                positionAttribute.Values.Add(positions[i].ToVector3F());
                colorAttribute.AddColor(Color.Red);
            }

            Mesh mesh = new Mesh();
            mesh.PrimitiveType = PrimitiveType.LineStrip;
            mesh.Attributes.Add(positionAttribute);
            mesh.Attributes.Add(colorAttribute);

            _polyline.Set(_window.Context, mesh);

            ///////////////////////////////////////////////////////////////////

            double scale = 1.25 * _globeShape.Radii.MaximumComponent;
            _plane.XAxis = scale * _p.Normalize();
            _plane.YAxis = scale * _p.Cross(_q).Cross(_p).Normalize();
        }
        private void CreateScene()
        {
            DisposeScene();

            _ellipsoid = new TessellatedGlobe();
            _ellipsoid.Shape = _globeShape;
            _ellipsoid.NumberOfSlicePartitions = 64;
            _ellipsoid.NumberOfStackPartitions = 32;

            ///////////////////////////////////////////////////////////////////

            Mesh mesh = GeographicGridEllipsoidTessellator.Compute(_globeShape,
                64, 32, GeographicGridEllipsoidVertexAttributes.Position);

            _wireframe = new Wireframe(_window.Context, mesh);
            _wireframe.Width = 2;

            ///////////////////////////////////////////////////////////////////

            _axes = new Axes();
            _axes.Length = 1.5;
            _axes.Width = 3;

            ///////////////////////////////////////////////////////////////////

            Vector3D p = _globeShape.ToVector3D(new Geodetic3D(0, Trig.ToRadians(45), 0));
            Vector3D deticNormal = _globeShape.GeodeticSurfaceNormal(p);
            Vector3D centricNormal = Ellipsoid.CentricSurfaceNormal(p);

            double normalLength = _globeShape.MaximumRadius;
            Vector3D pDetic = p + (normalLength * deticNormal);
            Vector3D pCentric = p + (normalLength * centricNormal);

            VertexAttributeFloatVector3 positionAttribute = new VertexAttributeFloatVector3("position", 4);
            positionAttribute.Values.Add(p.ToVector3F());
            positionAttribute.Values.Add(pDetic.ToVector3F());
            positionAttribute.Values.Add(p.ToVector3F());
            positionAttribute.Values.Add(pCentric.ToVector3F());

            VertexAttributeRGBA colorAttribute = new VertexAttributeRGBA("color", 4);
            colorAttribute.AddColor(Color.DarkGreen);
            colorAttribute.AddColor(Color.DarkGreen);
            colorAttribute.AddColor(Color.DarkCyan);
            colorAttribute.AddColor(Color.DarkCyan);

            Mesh polyline = new Mesh();
            polyline.PrimitiveType = PrimitiveType.Lines;
            polyline.Attributes.Add(positionAttribute);
            polyline.Attributes.Add(colorAttribute);

            _normals = new Polyline();
            _normals.Set(_window.Context, polyline);
            _normals.Width = 3;

            ///////////////////////////////////////////////////////////////////
            Font font = new Font("Arial", 24);
            IList<Bitmap> labelBitmaps = new List<Bitmap>(2);
            labelBitmaps.Add(Device.CreateBitmapFromText("Geodetic", font));
            labelBitmaps.Add(Device.CreateBitmapFromText("Geocentric", font));
            font.Dispose();

            TextureAtlas atlas = new TextureAtlas(labelBitmaps);

            _labels = new BillboardCollection(_window.Context, 2);
            _labels.Texture = Device.CreateTexture2D(atlas.Bitmap, TextureFormat.RedGreenBlueAlpha8, false);
            _labels.Add(new Billboard()
            {
                Position = pDetic,
                TextureCoordinates = atlas.TextureCoordinates[0],
                Color = Color.DarkGreen,
                HorizontalOrigin = HorizontalOrigin.Right,
                VerticalOrigin = VerticalOrigin.Bottom
            });
            _labels.Add(new Billboard()
            {
                Position = pCentric,
                TextureCoordinates = atlas.TextureCoordinates[1],
                Color = Color.DarkCyan,
                HorizontalOrigin = HorizontalOrigin.Right,
                VerticalOrigin = VerticalOrigin.Bottom
            });

            atlas.Dispose();

            ///////////////////////////////////////////////////////////////////
            Vector3D east = Vector3D.UnitZ.Cross(deticNormal);
            Vector3D north = deticNormal.Cross(east);

            _tangentPlane = new Plane(_window.Context);
            _tangentPlane.Origin = p;
            _tangentPlane.XAxis = east;
            _tangentPlane.YAxis = north;
            _tangentPlane.OutlineWidth = 3;
        }