在C#中将Ascii地图(度,分,秒经度和纬度+深度)转换为3D地图

时间:2019-06-21 07:51:33

标签: c#

我有一个Ascii(.asc)格式的文件,其中包含纬度和经度信息以及某个区域的深度。 我想以3D形式显示地图,但我不知道该怎么做! 请帮助我

我正在设计3D环境,但我不知道如何在此环境中设计针对区域的信息

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace TerrainGeneratorTutorial0._1
{
    public partial class Form1 : Form
    {
        private Device device = null;
        private VertexBuffer vb = null;
        private IndexBuffer ib = null;

        private const int terWidth = 64;
        private const int terLength = 64;
        private float moveSpeed = 0.2f;
        private float turnSpeed = 0.02f;
        private float rotY = 0; // between 0 and 2*Math.PI (=360°)
        private float tempY = 0;

        private const float raiseConst = 0.05f;

        private float rotXZ = 0;
        private float tempXZ = 0;

        private static int vertCount = terWidth * terLength; //amount of vertices
        private static int indCount = (terWidth - 1) * (terLength - 1) * 6; //amount of indices

        private Vector3 camPosition, camLookAt, camUp;

        CustomVertex.PositionColored[] verts = null; //our vertices here can only store position and color information

        bool isMiddleMouseDown = false;
        bool isLeftMouseDown = false;


        private static int[] indices = null;

        private FillMode fillMode = FillMode.WireFrame;
        private Color backgroundColor = Color.Black;

        private bool invalidating = true;

        private Bitmap heightmap = null;

        public Form1()
        {
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true); //this needs to be set so the invalidate() function in the paint event works properly
            InitializeComponent();

            InitializeGraphics();
            InitializeEventHandler();
        }
        private void InitializeGraphics()
        {
            PresentParameters pp = new PresentParameters();
            pp.Windowed = true;
            pp.SwapEffect = SwapEffect.Discard; //just how the stuff should be moved from the backbuffer to the front buffer
            pp.EnableAutoDepthStencil = true;
            pp.AutoDepthStencilFormat = DepthFormat.D16;

            device = new Device(0, DeviceType.Hardware, this, CreateFlags.HardwareVertexProcessing, pp);

            GenerateVertex();
            GenerateIndex();

            vb = new VertexBuffer(typeof(CustomVertex.PositionColored), vertCount, device, Usage.Dynamic | Usage.WriteOnly, CustomVertex.PositionColored.Format, Pool.Default);
            OnVertexBufferCreate(vb, null);

            ib = new IndexBuffer(typeof(int), indCount, device, Usage.WriteOnly, Pool.Default);
            OnIndexBufferCreate(ib, null);

            //Initial Camera position
            camPosition = new Vector3(terLength/2, 4.5f, -3.5f);
            camUp = new Vector3(0, 1, 0); // the cameras up is looking actually up on the Y axis e.g. (0,-1,0) would turn the camera upside down
        }
        private void InitializeEventHandler()
        {
            vb.Created += new EventHandler(OnVertexBufferCreate);
            ib.Created += new EventHandler(OnIndexBufferCreate);

            this.KeyDown += new KeyEventHandler(OnKeyDown);
            this.MouseWheel += new MouseEventHandler(OnMouseScroll);

            this.MouseMove += new MouseEventHandler(OnMouseMove);
            this.MouseDown += new MouseEventHandler(OnMouseDown);
            this.MouseUp += new MouseEventHandler(OnMouseUp);

        }

        private void OnIndexBufferCreate(object sender, EventArgs e)
        {
            IndexBuffer buffer = (IndexBuffer)sender;
            buffer.SetData(indices, 0, LockFlags.None); //puts all indices from the int array into the index buffer
        }
        private void OnVertexBufferCreate(object sender, EventArgs e)
        {
            VertexBuffer buffer = (VertexBuffer)sender;
            buffer.SetData(verts, 0, LockFlags.None); //puts all vertices from the vertex array into the vertex buffer
        }
        private void SetupCamera()
        {
            camLookAt.X = (float)Math.Sin(rotY) + camPosition.X + (float)(Math.Sin(rotXZ) * Math.Sin(rotY));    //      
            camLookAt.Y =  (float) Math.Sin(rotXZ) + camPosition.Y;  // Bind the camera lookAt somehow with the camera position, so once we move around we also move the lookAt
            camLookAt.Z = (float)Math.Cos(rotY) + camPosition.Z + (float)(Math.Sin(rotXZ) * Math.Cos(rotY));  //


            device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, this.Width / this.Height, 1.0f, 1000.0f);  //sets the perspective and the field of view of the camer
            device.Transform.View = Matrix.LookAtLH(camPosition, camLookAt, camUp); //sets the position, the lookat and the up vector of the camera

            device.RenderState.Lighting = false;
            device.RenderState.CullMode = Cull.CounterClockwise; //sets which site of the triangles should be shown
            device.RenderState.FillMode = fillMode; //this sets the mode so we can actually see the triangle construct of the terrain
        }
        private void Form1_Paint(object sender, PaintEventArgs e) //here is the drawing loop
        {
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, backgroundColor, 1, 0);

            SetupCamera();

            device.BeginScene();

            device.VertexFormat = CustomVertex.PositionColored.Format;

            device.SetStreamSource(0, vb, 0); //tells the device where to receive the vertex information from
            device.Indices = ib; //tells the device where to receive the index information from

            device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertCount, 0, indCount / 3); //draws the triangles depending on the style we set it using the information from indices

            device.EndScene();
            device.Present();

            menuStrip1.Update();

            if (invalidating)
            {
                this.Invalidate();//this makes the form redraw itself over and over so that we have some kind of a loop 
            }
        }
        private void GenerateVertex()
        {
            verts = new CustomVertex.PositionColored[vertCount];

            int k = 0;
            for (int z = 0; z < terWidth; z++)
            {
                for (int x = 0; x < terLength; x++)
                {
                    verts[k].Position = new Vector3(x, 0, z);
                    verts[k].Color = Color.White.ToArgb();
                   k++;
                }
            }
        }
        private void GenerateIndex() // Generating all the indices vor the Index buffer (Her we tell how to connect the vertices to creat triangles)
        {
            indices = new int[indCount];

            int k = 0;
            int l = 0;
            for (int i = 0; i < indCount; i += 6)
            {
                indices[i] = k;                     //
                indices[i + 1] = k + terLength;     // left triangle of the square
                indices[i + 2] = k + terLength + 1; //

                indices[i + 3] = k;                   //
                indices[i + 4] = k + terLength + 1;   // right triangle of the square
                indices[i + 5] = k + 1;               //
                k++;
                l++;
                if (l == terLength - 1) //once one line of rectangles is created and the end of the line is beeing reached skip one k
                {
                    l = 0;
                    k++;
                }
            }
        }

        private void LoadHeightmap()
        {
            verts = new CustomVertex.PositionColored[vertCount];

            int k = 0;

            using(OpenFileDialog ofd = new OpenFileDialog())
            {
                ofd.Title = "Load Heightmap";
                ofd.Filter = "Bitmap files (*.bmp)|*.bmp";
                ofd.InitialDirectory = Application.StartupPath;
                if (ofd.ShowDialog(this) == DialogResult.OK)
                {
                    heightmap = new Bitmap(ofd.FileName);
                    Color pixelCol;

                    for (int z = 0; z < terWidth; z++)
                    {
                        for (int x = 0; x < terLength; x++)
                        {
                            if(heightmap.Size.Width>x && heightmap.Size.Height > z)
                            {
                                pixelCol = heightmap.GetPixel(x, z);
                                verts[k].Position = new Vector3(x, (float)pixelCol.B / 15 - 10, z);
                                verts[k].Color = pixelCol.ToArgb();
                            }
                            else
                            {
                                verts[k].Position = new Vector3(x, 0, z);
                                verts[k].Color = Color.White.ToArgb();
                            }

                            k++;
                        }
                    }
                }
            }
        }

        private void OnKeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case (Keys.W):
                {
                    camPosition.X += moveSpeed * (float)Math.Sin(rotY);
                    camPosition.Z += moveSpeed * (float)Math.Cos(rotY);
                    break;
                }
                case (Keys.S):
                {
                    camPosition.X -= moveSpeed * (float)Math.Sin(rotY);
                    camPosition.Z -= moveSpeed * (float)Math.Cos(rotY);
                    break;
                }
                case (Keys.D):
                {
                    camPosition.X += moveSpeed * (float)Math.Sin(rotY + Math.PI / 2);
                    camPosition.Z += moveSpeed * (float)Math.Cos(rotY + Math.PI / 2);
                    break;
                }

                case (Keys.A):
                {
                    camPosition.X -= moveSpeed * (float)Math.Sin(rotY + Math.PI / 2);
                    camPosition.Z -= moveSpeed * (float)Math.Cos(rotY + Math.PI / 2);
                    break;
                }
                case (Keys.Q):
                {
                    rotY -= turnSpeed;
                    break;
                }
                case (Keys.E):
                {
                    rotY += turnSpeed;
                    break;
                }
                case (Keys.Up):
                {
                    if(rotXZ < Math.PI / 2)
                    {
                        rotXZ += turnSpeed;
                    }                            
                    break;
                }
                case (Keys.Down):
                {
                    if (rotXZ > -Math.PI / 2)
                    {
                        rotXZ -= turnSpeed;
                    }
                    break;
                }
            }
        }
        private void OnMouseScroll(object sender, MouseEventArgs e)
        {
            camPosition.Y -= e.Delta * 0.001f;
        }

        private void OnMouseMove(object sender, MouseEventArgs e)
        {
            if (isMiddleMouseDown)
            {
                rotY = tempY + e.X * turnSpeed;

                float tmp = tempXZ - e.Y * turnSpeed / 4;
                if (tmp < Math.PI / 2 && tmp > -Math.PI / 2)
                {
                    rotXZ = tmp;
                }             
            }
            if (isLeftMouseDown)
            {
                Point mouseMoveLocation = new Point(e.X, e.Y);
                PickingTriangle(mouseMoveLocation);
            }       
        }

        private void OnMouseDown(object sender, MouseEventArgs e)
        {
            switch (e.Button)
            {
                case (MouseButtons.Middle):
                {
                    tempY = rotY - e.X * turnSpeed;
                    tempXZ = rotXZ + e.Y * turnSpeed / 4;

                    isMiddleMouseDown = true;
                    break;
                }
                case (MouseButtons.Left):
                {
                    isLeftMouseDown = true;

                    Point mouseDownLocation = new Point(e.X, e.Y);
                    PickingTriangle(mouseDownLocation);
                    break;
                }
            }
        }
        private void OnMouseUp(object sender, MouseEventArgs e)
        {
            switch (e.Button)
            {
                case (MouseButtons.Middle):
                {
                    isMiddleMouseDown = false;
                    break;
                }
                case (MouseButtons.Left):
                {
                    isLeftMouseDown = false;
                    break;
                }
            }
        }
        private void PickingTriangle(Point mouseLocation)
        {
            IntersectInformation hitLocation;

            Vector3 near, far, direction;

            near = new Vector3(mouseLocation.X, mouseLocation.Y, 0);
            far = new Vector3(mouseLocation.X, mouseLocation.Y, 100);

            near.Unproject(device.Viewport, device.Transform.Projection, device.Transform.View, device.Transform.World);
            far.Unproject(device.Viewport, device.Transform.Projection, device.Transform.View, device.Transform.World);

            direction = near - far;

            for(int i=0; i<indCount; i += 3)
            {
                if(Geometry.IntersectTri(verts[indices[i]].Position, verts[indices[i+1]].Position, verts[indices[i+2]].Position,near, direction, out hitLocation))
                {
                    verts[indices[i]].Color = Color.Red.ToArgb();
                    verts[indices[i+1]].Color = Color.Red.ToArgb();
                    verts[indices[i+2]].Color = Color.Red.ToArgb();


                    verts[indices[i]].Position += new Vector3(0, raiseConst, 0); 
                    verts[indices[i+1]].Position += new Vector3(0, raiseConst, 0);
                    verts[indices[i+2]].Position += new Vector3(0, raiseConst, 0);

                    vb.SetData(verts, 0, LockFlags.None);
                }
            }
        }

        private void solidToolStripMenuItem_Click(object sender, EventArgs e)
        {
            fillMode = FillMode.Solid;
            solidToolStripMenuItem.Checked = true;
            wireframeToolStripMenuItem.Checked = false;
            pointToolStripMenuItem.Checked = false;
        }
        private void wireframeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            fillMode = FillMode.WireFrame;
            solidToolStripMenuItem.Checked = false;
            wireframeToolStripMenuItem.Checked = true;
            pointToolStripMenuItem.Checked = false;
        }
        private void pointToolStripMenuItem_Click(object sender, EventArgs e)
        {
            fillMode = FillMode.Point;
            solidToolStripMenuItem.Checked = false;
            wireframeToolStripMenuItem.Checked = false;
            pointToolStripMenuItem.Checked = true;
        }

        private void backgroundColorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ColorDialog cd = new ColorDialog();

            invalidating = false;
            if (cd.ShowDialog(this) == DialogResult.OK)
            {
                backgroundColor = cd.Color;
            }
            invalidating = true;
            this.Invalidate();
        }

        private void loadHeightmapToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LoadHeightmap();
            vb.SetData(verts, 0, LockFlags.None);
        }

        private void resetToolStripMenuItem_Click(object sender, EventArgs e)
        {
            GenerateVertex();
            vb.SetData(verts, 0, LockFlags.None);
        }
    }  
}

0 个答案:

没有答案