精华内容
下载资源
问答
  • ArcGIS Engine下实现地图输出

    千次阅读 2017-04-21 10:32:17
    ArEngine给我们提供了很多地图输出的方式,包括文件方式和打印等,这些方式又受...思路:采用IActiveView接口下的output方法,可以将地图输出为上十格式,具体的格式受IExport类型限制,如ExportBMP,ExportPN...

     

    ArEngine给我们提供了很多种将地图输出的方式,包括文件方式和打印等,这些方式又受不同参数的控制有着不同的效果。要想得到符合我们要求的效果,就必须了解这些方法所表达的意思和参数的内容,下面简要说明一下,其它的可以参考开发文档。

    思路:采用IActiveView接口下的output方法,可以将地图输出为上十种格式,具体的格式受IExport类型限制,如ExportBMP,ExportPNG、ExportJPEG等,下面以输出为JPEG格式来说明。

    首先定义ExportJPEG的实例pExport,然后设置其相关的参数,过程比较简单,这里重点描述一下相关的参数设置。

    方法:OutPut(hdc, Dpi, pixelBounds, VisibleBounds, TrackCancel )

    1、这里hdc是输出设备,由pExport.StartExporting指定;

    2、Dpi是输出图片的精度,但是这里这个resolution并不能改变图片的精度,无论设置多大的dpi,输出同一范围图片的大小、精度都是一样的。要想改变精度,得指定IOutputRasterSettings::ResampleRatio这个参数,可以设置1—5个级别的采样率,在输出图片很大的时候这个参数能提高图片的质量;

    3、PixelBounds设置的是输出像素所占的范围;

    4、VisibleBounds指定地图可视的范围,这个范围是以地图坐标为单位的,以当前MapExtent为基准来控制放大、缩小视图;

    5、还有个参数是pExpotrt.PixelBounds,定义的是输出图片的大小,即图片尺寸,相当于画布大小。当输出像素的范围大于图片大小的时候就会裁切图片,只输出部分地图;当它小于图片尺寸时地图会缩小到画布的一角。

    综上所述,VisibleBounds或者像素范围和图片大小都可以设置地图的输出范围,一般按照具体的需要采用其中一种就可以了。

    最后一点说明一下,DeviceFrame是当前设备范围,在ArcMap中就是地图所在的客户区,以左上角为起点(0,0);ExportFrame和DeviceFrame差不多,只是可能比前者略小一点;Map Extent一般是指地图范围,采用的是地图单位。整个AO体系里面有很多不同的Extent范围,弄清它们之间的关系对开发人员来说是很必要的。

     

    示例:

     

    1、界面如下:

    2、实现步骤

    a、创建新窗体,ExportMapForm

    b、添加控件ComboBox,TextBox,Button等,具体参数设置如下:

    TextBox

    txtFileName

    用于显示输出路径,ReadOnly设置为true

    Button

    btnSave

    显示“路径”,用于设置文件导出位置

    NumbericUpDown

    txtResolution

    选择分辨率,默认value=96

    CombiBox

    cmbPageSize

    显示“图片尺寸”,集合:自定义大小、A4A3A2A1A0

    TextBox

    txtWidth

    宽度

    TextBox

    txtLength

    长度

    RadioButton

    radioButton1

    显示“英寸”

    RadioButton

    radioButton2

    显示“厘米”

    RadioButton

    radioButton3

    显示“像素”

    c、框体的源代码如下:

    using System;  
    using System.Collections.Generic;  
    using System.ComponentModel;  
    using System.Data;  
    using System.Drawing;  
    using System.Text;  
    using System.Windows.Forms;  
    using ESRI.ArcGIS.Carto;  
    using ESRI.ArcGIS.Geodatabase;  
    using ESRI.ArcGIS.Output;  
    using ESRI.ArcGIS.esriSystem;  
    using ESRI.ArcGIS.Geometry;  
    using System.Text.RegularExpressions;  
    using ESRI.ArcGIS.Controls;  
      
      
    namespace GIS  
    {  
        public partial class ExportMapForm : Form  
        {  
            private double pWidth, pHeight;   
            private IActiveView pActiveView=null;  
            public ExportMapForm(IHookHelper hookHelper)  
            {  
                InitializeComponent();  
                pActiveView = hookHelper.ActiveView;  
            }  
            private void btnSave_Click(object sender, EventArgs e)  
            {  
                this.saveMapFileDialog.ShowDialog();  
                this.txtFileName.Text = saveMapFileDialog.FileName;  
            }  
      
            private void cmdOK_Click(object sender, EventArgs e)  
            {  
                this.Cursor = Cursors.WaitCursor;  
                if (!IsNumbericA(txtWidth.Text))  
                {  
                    MessageBox.Show("请输入数字!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);  
                    txtWidth.Focus();  
                    return;  
                }  
                if (!IsNumbericA(txtHeight.Text))  
                {  
                    MessageBox.Show("请输入数字!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);  
                    txtHeight.Focus();  
                    return;  
                }  
                if (txtResolution.Value > 1)  
                {  
                    ExportTool();  
                }  
                this.Cursor = Cursors.Default;  
            }  
      
            private void ExportTool()  
            {  
                 IExport pExport=null;  
    //           IExportJPEG pExportFormat;  
                 IWorldFileSettings pWorldFile=null;  
                 IExportImage pExportType;  
                 IEnvelope pDriverBounds = null;  
      //         int lScreenResolution ;  
                 ESRI.ArcGIS.Display.tagRECT userRECT=new ESRI.ArcGIS.Display.tagRECT();  
                 IEnvelope pEnv=new EnvelopeClass();  
     //          double dWidth;  
     //          double dHeight;  
                 int lResolution;  
                 lResolution = Convert.ToInt32(this.txtResolution.Value);  
                switch (this.saveMapFileDialog.Filter.ToString().Trim().Substring(0,3))  
                {  
                    case "jpg":  
                        pExport = new ExportJPEGClass();  
                        break;  
                    case "bmp":  
                        pExport = new ExportBMPClass();  
                        break;  
                    case "gif":  
                        pExport = new ExportGIFClass();  
                        break;  
                    case "tif":  
                        pExport = new ExportTIFFClass();  
                        break;  
                    case "png":  
                        pExport = new ExportPNGClass();  
                        break;  
                    case "emf":  
                        pExport = new ExportEMFClass();  
                        break;  
                    case "pdf":  
                        pExport = new ExportPDFClass();  
                        break;  
                    case ".ai":     
                        pExport = new ExportAIClass();  
                        break;  
                    case "svg":  
                        pExport = new ExportSVGClass();  
                        break;  
                    default:  
                        pExport = new ExportJPEGClass();  
                        break;  
                }  
           
                if (this.txtFileName.Text.ToString().Trim() != "")  
                {  
                    if (System.IO.File.Exists(this.txtFileName.Text.ToString()) == true)  
                    {  
                        MessageBox.Show("该文件已经存在,请重新命名!");  
                        this.txtFileName.Text = "";  
                        this.txtFileName.Focus();  
                    }  
                    else  
                    {  
                        pExport.ExportFileName = this.txtFileName.Text;  
                        pExport.Resolution = lResolution;  
                        pExportType = pExport as IExportImage;  
                        pExportType.ImageType = esriExportImageType.esriExportImageTypeTrueColor;  
                        pEnv = pActiveView.Extent;  
                        pWorldFile = (IWorldFileSettings)pExport;  
                        pWorldFile.MapExtent = pEnv;  
                        pWorldFile.OutputWorldFile = false;  
                        userRECT.top = 0;  
                        userRECT.left = 0;  
                        userRECT.right = Convert.ToInt32(pWidth);  
                        userRECT.bottom = Convert.ToInt32(pHeight);  
                        pDriverBounds = new EnvelopeClass();  
                        pDriverBounds.PutCoords(userRECT.top, userRECT.bottom, userRECT.right, userRECT.top);  
                        pExport.PixelBounds = pDriverBounds;  
      
                        ITrackCancel pTrackCancel = new TrackCancelClass();  
                        pActiveView.Output(pExport.StartExporting(), lResolution, ref userRECT, pActiveView.Extent, pTrackCancel);  
                        pExport.FinishExporting();  
                        MessageBox.Show("打印图片保存成功!", "保存", MessageBoxButtons.OK);  
                        this.Close();  
      
                    }  
      
                }  
                else  
                {  
                    MessageBox.Show("请保存文件!");  
                }  
      
            }  
            public IActiveView ResActiveView  
            {  
                get {  
                    return pActiveView;  
                }  
                set {  
                    pActiveView = value;  
                }  
            }  
      
            private void txtResolution_ValueChanged(object sender, EventArgs e)  
            {  
                 cmbPageSize_SelectedValueChanged(null,null);  
                 if (this.radioButton3.Checked == true)  
                 {  
                     this.txtWidth.Text = pWidth.ToString(".00");  
                     this.txtHeight.Text = pHeight.ToString(".00");  
                 }  
            }  
      
            private void cmbPageSize_SelectedValueChanged(object sender, EventArgs e)  
            {  
                switch(cmbPageSize.Text)  
                {  
                    case "自定义大小":  
                        txtWidth.Focus();  
                        break;  
                    case "A4":  
                        showWH(21,29.7);  
                        break;  
                    case"A3":  
                        showWH(29.7, 42);  
                        break;  
                    case"A2":  
                        showWH(42, 59.4);  
                        break;  
                    case"A1":  
                        showWH(59.4, 84.1);  
                        break;  
                   case"A0":  
                        showWH(84.1, 118.9);  
                        break;  
                }      
            }  
      
    //显示宽度和高度  
    //传入的参数必须是厘米  
            private void showWH(double pW,double pH)  
           {  
               pWidth = Convert.ToDouble((pW / 2.54) * Convert.ToDouble(txtResolution.Value));  
               pHeight = Convert.ToDouble((pH / 2.54) * Convert.ToDouble(txtResolution.Value));  
                if (this.radioButton1.Checked == true)  
                {  
                    this.txtWidth.Text = Convert.ToDouble(pW / 2.54).ToString(".00");  
                    this.txtHeight.Text = Convert.ToDouble(pH / 2.54).ToString(".00");  
                }  
                else if (this.radioButton2.Checked == true)  
                {  
                    this.txtWidth.Text = pW.ToString(".00");  
                    this.txtHeight.Text = pH.ToString(".00");  
                }  
                else  
                {  
                    this.txtWidth.Text = pW.ToString(".00");  
                    this.txtHeight.Text = pH.ToString(".00");  
                }  
            }  
      
            private void txtWidth_TextChanged(object sender, EventArgs e)  
            {  
                //if (!IsNumbericA(txtWidth.Text))  
                //{  
                //    MessageBox.Show("请输入数字!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);  
                //    return;  
                //}  
                if (this.radioButton1.Checked == true)  
                {  
                    pWidth = Convert.ToDouble(txtWidth.Text) * Convert.ToDouble(txtResolution.Value);  
      
                }  
                else if (this.radioButton2.Checked == true)  
                {  
                    pWidth = Convert.ToDouble(Convert.ToDouble(txtWidth.Text) / 2.54) * Convert.ToDouble(txtResolution.Value);  
      
                }else  
                {  
                    pWidth = Convert.ToDouble(txtWidth.Text);  
                }  
            }  
      
            private void txtHeight_TextChanged(object sender, EventArgs e)  
            {  
                //if (!IsNumbericA(txtHeight.Text))  
                //{  
                //    MessageBox.Show("请输入数字!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);  
                //    return;  
                //}  
                      
                if (this.radioButton1.Checked == true)  
                {  
                    pHeight = Convert.ToDouble(txtHeight.Text) * Convert.ToDouble(txtResolution.Value);  
      
                }  
                else if (this.radioButton2.Checked == true)  
                {  
                    pHeight = Convert.ToDouble(Convert.ToDouble(txtHeight.Text) / 2.54) * Convert.ToDouble(txtResolution.Value);  
      
                }  
                else  
                {  
                    pHeight = Convert.ToDouble(txtHeight.Text);  
                }  
            }  
      
            private void radioButton1_Click(object sender, EventArgs e)  
            {  
                this.txtWidth.Text = Convert.ToDouble(pWidth / Convert.ToDouble(txtResolution.Value)).ToString(".00");  
                this.txtHeight.Text = Convert.ToDouble(pHeight / Convert.ToDouble(txtResolution.Value)).ToString(".00");  
            }  
      
            private void radioButton2_Click(object sender, EventArgs e)  
            {  
                     this.txtWidth.Text = Convert.ToDouble(2.54 * pWidth / Convert.ToDouble(txtResolution.Value)).ToString(".00");  
                    this.txtHeight.Text =Convert.ToDouble(2.54 * pHeight / Convert.ToDouble(txtResolution.Value)).ToString(".00");  
      
            }  
      
            private void radioButton3_Click(object sender, EventArgs e)  
            {  
                this.txtWidth.Text = pWidth.ToString(".00");  
                this.txtHeight.Text = pHeight.ToString(".00");  
      
            }  
            #region 通用函数  
            /// <summary>  
            /// 是否大于0的数字  
            /// </summary>  
            /// <param name="v"></param>  
            /// <returns></returns>  
            private bool IsNumbericA(string v)  
            {  
                return ((this.IsIntegerA(v)) || (this.IsFloatA(v)));  
            }  
            /// <summary>  
            /// 是否正浮点数  
            /// </summary>  
            /// <param name="v"></param>  
            /// <returns></returns>  
            private bool IsFloatA(string v)  
            {  
                string pattern = @"^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$";  
                Regex reg = new Regex(pattern);  
                return reg.IsMatch(v);  
            }  
            /// <summary>  
            /// 是否正整数  
      
      
            /// </summary>  
            /// <param name="v"></param>  
            /// <returns></returns>  
            private bool IsIntegerA(string v)  
            {  
                string pattern = @"^[0-9]*[1-9][0-9]*$";  
                Regex reg = new Regex(pattern);  
                return reg.IsMatch(v);  
            }  
            #endregion  
      
            private void frmResource_FormClosing(object sender, FormClosingEventArgs e)  
            {  
                if (e.CloseReason == CloseReason.UserClosing)  
                {  
                    e.Cancel = true;  
                    this.Hide();  
                }  
            }  
        }  
    }  

     

    d、框体的调用:

    //参数定义      
        IHookHelper layout_hookHelper = new HookHelperClass();  
    //参数赋值  
        layout_hookHelper.Hook = this.axPageLayoutControl1.Object;  
    
    ExportMapForm EMFrm = new ExportMapForm(layout_hookHelper);  
    EMFrm.ShowDialog();  

     

     

     

     

    展开全文
  • java初学者,最近写了一个走迷宫的代码,迷宫地图是存储在二维数组中的,0代表路, 1代表墙,2代表终点,3代表找到的路径。 希望能给一块代码能够弹出一个窗口显示迷宫,并且不同的类型显示不一样的颜色。 类似的也...
  • 如何输出一幅要素齐全的地图

    千次阅读 2019-08-28 10:05:34
    本篇博文小编为大家分享如何输出一幅要素齐全的地图,首先来了解一下什么是地图呢?地图是按照一定的法则,有选择地以二维或多维形式与手段在平面或球面上表示地球若干现象的图形或图像,它具有严格的数学基础、符号...

    作者:dongyx

            本篇博文小编为大家分享如何输出一幅要素齐全的地图,首先来了解一下什么是地图呢?地图是按照一定的法则,有选择地以二维或多维形式与手段在平面或球面上表示地球若干现象的图形或图像,它具有严格的数学基础、符号系统、文字注记,并能用地图概括原则,科学地反映出自然和社会经济现象的分布特征及其相互关系。
            一幅完整的地图是需要有地图要素的。而地图要素分为数学要素、地理要素和辅助要素。下面我将从以上三种要素为大家详细介绍如何在SuperMap iDesktop 桌面软件(以下简称桌面软件)中完成这几类要素。
            首先在打开桌面软件并打开一个工作空间,在工作空间管理器下右键布局节点–新建布局,选择空白模板。在’对象操作’选项卡下选择地图,添加一幅地图到布局中,如果地图按钮是灰色是因为打开的工作空间中没有地图,需要创建一幅地图并保存,再添加到布局中,如图所示:
    在这里插入图片描述
    一、数学要素
            数学要素:具有按一定的数学法则构成的或具有数学意义的地图要素,包括坐标网、控制点、地图比例尺及地图定向要素等。
            比例尺:是表示图上一条线段的长度与地面相应线段的实际长度之比,比例尺=图上距离/实际距离。点击’对象操作’选项卡下方的’比例尺’按钮,在布局中的指定位置添加比例尺,可以右键比例尺属性,弹出比例尺属性框:在属性框中设置比例尺类型(桌面软件主要提供两种类型的比例尺:数字比例尺、线段式比例尺)、比例尺单位等参数;
    在这里插入图片描述
    在这里插入图片描述
            地图定向要素(指北针):主要是指示地图的方向。点击’对象操作’选项卡下方的’指北针’按钮,在布局中的指定位置添加指北针,一般是在地图的右上方,也可根据地图的轮廓自定义设置。右键指北针–属性,弹出属性框设置指北针的样式:
    在这里插入图片描述
    在这里插入图片描述
    二:地理要素
            地理要素:是指地图内容,包括自然地理要素与社会经济要素。在配置地图的时候已经添加地图的内容,包括街道、行政区域、POI点等。在这就不赘述了。
    三、辅助要素
            辅助要素:也称整饰要素,主要指便于读图和用图的某些内容。例如:图名、图号、图例和地图资料说明,以及图内各种文字、数字注记等。
            文本注记:在’对象操作’选项卡下点击’文本’按钮,可在布局的任何位置添加文本,添加完文本后可在风格设置选项卡中设置文本的风格:包括文本的字体、大小、颜色等属性。
    在这里插入图片描述
            图例:图例是集中于地图一角或一侧的地图上各种符号和颜色所代表内容与指标的说明,有助于更好的认识地图。在’对象操作’选项卡下点击’图例’按钮,在布局中的指定位置添加图例,如图所示:
    在这里插入图片描述
            这时会发现图例内容太多,文本显示太小,文本超出布局外边界等问题,我们可以右键图例–拆分布局元素,这时我们可以修改布局的元素,包括删除图例子项、修改图例子项位置、修改文本颜色等属性。修改后结果如图所示:
    在这里插入图片描述
            当然在桌面软件软件中,不止添加这些要素,还可以添加很多要素来丰富我们的地图,图表格、图片、统计图表等。
    四、地图输出
            在完成一幅地图后就需要输出地图了,在桌面软件中提供了两种方式输出地图:
            1.输出为图片:支持输出JPG、PNG、位图、TIFF影像四种。右键布局窗口–输出为图片,在弹出框中设置图片类型、分辨率等。如果要输出高分辨率的图片建议输出为pdf。
    在这里插入图片描述
            结果如图所示:
    在这里插入图片描述
            2.输出为PDF:只需要设置文件名称和DPI即可输出高分辨率的PDF了。
    在这里插入图片描述
            结果如图所示:
    在这里插入图片描述

    展开全文
  • 相信我,看完之后,你会对BFS有全新的了解,彻底掌握BFS 只需要这一篇就足够啦,狗头 BFS路径表示 广度优先搜索顾名思义就是以迷宫里的无向图某一个点,借助队列,一层一层以该点为中心散开进行搜索,简单的BFS...

    相信我,看完之后,你会对BFS有种全新的了解,彻底掌握BFS
    只需要这一篇就足够啦,狗头

    BFS路径表示

    广度优先搜索顾名思义就是以迷宫里的无向图某一个点,借助队列,一层一层以该点为中心散开进行搜索,简单的BFS只能显示出最短路径的长度,这里探讨的就是如何实现BFS对最短路径的输出

    简单的BFS

    通过队列来实现,找到迷宫的起点(S)入队,出队列里面的队首,把队首上下左右相邻的点入队列,一直重复此操作,直到队列里面的所有元素都出队表示该迷宫不存在解,如果在队清空之前找到终点(T)的话,一层一层的遍历,找到的话就一定是最短路了,但是简单的BFS只能通过输出(now.d+1)来表示最短路的步数长度,不能表示出最短路径到底是什么?

    #include <iostream>
    #include <string>
    #include <queue>
    using namespace std;
    int n, m;//地图长宽
    string maze[110];//地图
    bool vis[110][110];//访问标记数组
    int dir[4][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};//方向变化
    bool in(int x, int y) {//确保在地图里面
        return 0 <= x && x < n && 0 <= y && y < m;
    }
    struct node{//定义node类型的结构体
        int x,y,d;//d表示路径
        node(int xx,int yy,int dd){//便于输入结构体里面的值
            x=xx;
            y=yy;
            d=dd;
        }
    };
    int bfs(int sx,int sy){
        queue<node>q;
        q.push(node(sx,sy,0));//将起点放入
        vis[sx][sy]=true;
        while(!q.empty()){//队列如果不为空继续
            node now=q.front();//找到队首
            q.pop();//队首出队
            for(int i=0;i<4;i++){
                int tx=now.x+dir[i][0];//周围遍历
                int ty=now.y+dir[i][1];
                if(in(tx,ty)&&maze[tx][ty]!='*'&&!vis[tx][ty]){//在界内且未遍历到
                    if(maze[tx][ty]=='T'){//如果是终点,BFS返回完成
                        return now.d+1;
                    }else{//如果不是不返回,标记该点入队继续搜索
                        vis[tx][ty]=true;
                        q.push(node(tx,ty,now.d+1));
                    }
                }
            }
        }
        return -1;//队空未找到就返回-1表示无解
    }
    int main() {
        cin >> n >> m;
        for (int i = 0; i < n; i++) {
            cin >> maze[i];
        }
        int x, y;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (maze[i][j] == 'S') {//找到迷宫的起点
                    x = i, y = j;
                }
            }
        }
        cout<<bfs(x,y)<<endl;
        return 0;    
    }
    

    我下午问了杰哥一下,杰哥给我介绍了两种思路下面的三种方法
    真的杰哥这些思路都是很经典很厉害的思想

    思路一

    就直接引用原话啦
    在这里插入图片描述
    我看着杰哥的代码理解了一下,大概意思就是
    1.首先正着从起点进行一遍BFS找到终点,再从终点反正来一遍BFS找到起点
    2.开创俩个数组dis1[N][N]和dis2[N][N]分别用于记录正向搜索每一次的出队时的每一个离起点的层数和反向搜索每一次的出队时的每一个点离起点的层数
    3.此时通过BFS我们已经知道最短路径的长度了,某个点只要能满足
    dis1[x][y]+dis2[x][y]=minrode
    那么这个点就一定是这个迷宫最短路径上面的点
    4.通过这样我们就能知道该迷宫的最短路径表示
    在这里插入图片描述
    代码展示如下:

    include<queue>
    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N=1005;//地图最大宽度 
    struct node{
    	int x,y;
    };
    queue<node>que;
    int n,m,minrode=0;
    int fx,fy;//记录终点的坐标值 
    char map[N][N];
    int dx[]={0,1,0,-1};
    int dy[]={1,0,-1,0};
    int dis1[N][N];//正向记录层数的数组 
    int dis2[N][N];//逆向记录层数的数组 
    bool mark[N][N];//用来标记是不是在最短路上 
    
    void BFS(int dis[][N],int sx,int sy){
    	
    	for(int i=0;i<n;i++)//初始化记录层数的dis数组 
    		for(int j=0;j<m;j++)
    			dis[i][j]=-1;
    	
    	while(!que.empty())que.pop();//初始化队列 
    	
    	que.push((node){sx,sy});//放入起点 
    	dis[sx][sy]=0;//(sx,sy)为起点 
    	
    	while(!que.empty()){
    		node cur=que.front();//当前状态
    		que.pop();
    		for(int i=0;i<4;i++){
    			node nxt;
    			nxt.x=cur.x+dx[i];
    			nxt.y=cur.y+dy[i];
    			if(map[nxt.x][nxt.y]=='#'){//墙壁无法通行 
    				continue;
    			} 
    			if(nxt.x>=0&&nxt.x<n&&nxt.y>=0&&nxt.y<m&&dis[nxt.x][nxt.y]==-1){
    				if(map[nxt.x][nxt.y]=='T'){
    					fx=nxt.x;fy=nxt.y;
    					minrode=dis[cur.x][cur.y]+1;
    					return ;
    				}
    				else{
    				que.push(nxt); 
    				dis[nxt.x][nxt.y]=dis[cur.x][cur.y]+1;//不断的记录层数
    			}
    			}
    		}
    	}	
    } 
    
    void Print(int x,int y){//对起点进行上下左右找,满足的mark=true的进行输出
    	printf("%d %d\n",x,y);	
    	for(int i=0;i<4;i++){//同样的进行遍历判断 
    		int nx=x+dx[i];
    		int ny=y+dy[i];
    		
    		if(nx<0||nx>=n||ny<0||ny>=m||map[nx][ny]=='#')continue; 
    		
    		if(dis1[nx][ny]<dis1[x][y])continue;//***不能往回走不能成环 
    		
    		if(mark[nx][ny]){
    			Print(nx,ny);
    			break;//避免输出多条最短路 
    		}
    	}
    }
    
    
    int main(){
    	int qx,qy;
    	scanf("%d%d",&n,&m);
    	for(int i=0;i<n;i++){
    		scanf("%s",map[i]);
    	}
    	for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (map[i][j] == 'S') {//找到迷宫的起点
                    qx = i;qy = j;
                }
            }
        }
    	BFS(dis1,qx,qy);//正向遍历 
    	BFS(dis2,fx,fy);//逆向遍历 
    	
    	memset(mark,0,sizeof(mark));//初始化最短路径记录数组 
    	
    	int total=minrode;
    
    	for(int i=0;i<n;i++){
    		for(int j=0;j<m;j++){
    			if(dis1[i][j]+dis2[i][j]==total){ 
    				mark[i][j]=true;//如果符合的话就是最短路,mark数组该点标记为true 
    			}
    		}
    	}
    	
    	Print(qx,qy);//调用print函数进行打印mark上面为true的点 
    	
    	return 0;
    }
    
    

    重点来了,关键关键关键!!!

    if(dis1[nx][ny]<dis1[x][y])continue;//***不能往回走不能成环 
    

    这一步真的print函数的重点所在
    为什么能打印满足mark数组等于true的点,我们要知道一个迷宫不只有一条最短路,有很多点都满足这个这个条件,那么万一出现这种成环的情况怎么办?
    在这里插入图片描述
    按照print函数层次遍历的算法,在A点可以会向右跑了,这样根本不是最短路,但是我们知道按照最短的遍历,dis1数组上面符合最短路的下一步的值一定会比这一步要大,我们在这里就可以做出限制条件,这样一方面就避免了往回回溯的可能,也避免了成环跑掉的可能,如果最短路不成环的话,我们也可以对已经打印出来的点进行标记,标记后不能打印,这样也可以实现避免了往回回溯的可能。

    思路二

    照片如图
    在这里插入图片描述
    这种思路大概就很像树型结构的寻找父亲,保存此时的坐标的信息和上一个坐标的信息,从终点往回不断的找,找父亲的父亲的父亲…直到起点为止,这样找下来也是一种最短路,像我这样就只能想到一些笨办法
    第一种就是直接建立树,这个树结点不仅保存该点的值,还保存下面儿子的地址和上面父亲结点的地址,这样一来直接就可以通过树来找到了,要写树代码量真的太大了,舍去。。。
    第二种就是建立结构体包含四个值,自己的XY坐标值,父亲的XY坐标值,从结点开始利用父亲的XY值遍历整个序列,看谁的XY和这里的对应就找到了父亲结点,依次进行,但是这样的复杂度太高了吧。。。果断舍去。。。
    好的,下面就介绍杰哥给的几种复杂度低的算法

    算法一

    这样怎么说呢,有点类似树的双亲孩子表示法,建立一个数组,里面装着每一个结点,结点后面跟着父亲结点在数组里面的下标值,就是一个结构体数组,通过每一个结点里面的父亲结点在数组里面的下标值就可以找到父亲结点了,通过在数组里面存储下标来回溯,很棒呀。
    在这里插入图片描述
    代码如下:

    /*Input:默认以(0,0)为起点,(4,4)为终点,随便改一下就行 
    5 5
    ...##
    ##.##
    ....#
    .##.#
    .....*/ 
    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N=1005;
    struct node{
     int x,y,lastId;
    }que[N*N];//最大有N*N个结点,没有墙全是路 
    
    int n,m;
    char map[N][N];
    
    int dx[]={0,1,0,-1};
    int dy[]={1,0,-1,0};
     
     void Print(node cur){
     if(cur.lastId!=-1){ 
      Print(que[cur.lastId]);//递归的算法,先找到第一个结点后输出值
     }
     printf("%d %d\n",cur.x,cur.y);//先找后输出就是顺序,先输出后找就是逆序 
    }
    
    int dis[N][N];
    void BFS(){
     
     memset(dis,-1,sizeof(dis));
     
     int L=1,R=0;
     que[++R]=(node){0,0,-1};//lastId=-1表示没有父亲 
     dis[0][0]=0;//(0,0)为起点 
     
     while(L<=R){
      node cur=que[L++];//当前状态
      
      for(int i=0;i<4;i++){
       node nxt;
       nxt.x=cur.x+dx[i];
       nxt.y=cur.y+dy[i];
       nxt.lastId=L-1;//当前状态的上一个状态在que数组中的下标为L-1 
       
       if(nxt.x==n-1&&nxt.y==m-1){//(n-1,m-1)为终点 
        Print(nxt);
        return; 
       }
       if(map[nxt.x][nxt.y]=='#'){//无法通行 
        continue;
       } 
       
       if(nxt.x>=0&&nxt.x<n&&nxt.y>=0&&nxt.y<m&&dis[nxt.x][nxt.y]==-1){
        que[++R]=nxt; 
        dis[nxt.x][nxt.y]=dis[cur.x][cur.y]+1;
       }
      }
     } 
    } 
    
    int main(){
     scanf("%d%d",&n,&m);
     for(int i=0;i<n;i++){
      scanf("%s",map[i]);
     }
     BFS();
     return 0;
    }
    

    算法二

    我真的有点被这个算法惊讶到了
    利用二维数组可以存储四个值,一般来数二维数组值可以存储三个值(x,y,本身点的信息),但是这里可以使用两个二维数组存储x,y,fx,fy的信息,分而和,和而找,既然知道了这四个信息,我们也就不难去回溯了
    代码如下:

    #include<queue>//还是和上面一样,(0,0)起点,(n-1,m-1)终点 
    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N=1005;
    
    struct node{
     int x,y;
    };
    
    int fax[N][N];
    int fay[N][N];
     
    queue<node>que;//对列 
    
    int n,m;
    char map[N][N];
    
    int dx[]={0,1,0,-1};
    int dy[]={1,0,-1,0};
     
    int dis[N][N];
    
    void Print(int x,int y){
     if(x!=-1&&y!=-1){
      Print(fax[x][y],fay[x][y]);
      printf("%d %d\n",x,y);
     }
    }
    
    void BFS(){
     
     memset(dis,-1,sizeof(dis));
     
     que.push((node){0,0});
     dis[0][0]=0;//(0,0)为起点 
     
     fax[0][0]=-1;
     fay[0][0]=-1;
     
     while(!que.empty()){
      node cur=que.front();//当前状态
      que.pop();
      for(int i=0;i<4;i++){
       node nxt;
       nxt.x=cur.x+dx[i];
       nxt.y=cur.y+dy[i];
       
       if(map[nxt.x][nxt.y]=='#'){//无法通行 
        continue;
       } 
       
       if(nxt.x>=0&&nxt.x<n&&nxt.y>=0&&nxt.y<m&&dis[nxt.x][nxt.y]==-1){
        que.push(nxt); 
        dis[nxt.x][nxt.y]=dis[cur.x][cur.y]+1;
        fax[nxt.x][nxt.y]=cur.x;
        fay[nxt.x][nxt.y]=cur.y;
       }
      }
     } 
    } 
    
    int main(){
     scanf("%d%d",&n,&m);
     for(int i=0;i<n;i++){
      scanf("%s",map[i]);
     }
     BFS();
     Print(n-1,m-1);
     return 0;
    }
    

    其他的简单的BFS一样,最为精华的我展示出来了

    void Print(int x,int y){
     if(x!=-1&&y!=-1){
      Print(fax[x][y],fay[x][y]);
      printf("%d %d\n",x,y);
     }
    }
    

    难以言语,分开来,合起来,分开来,再合起来…
    道家的思想,
    **分而治之,和而为之 **

    嗯嗯,就介绍完啦,你是否got到啦

    是不是肥肠的斯国一

    感谢杰哥这么细心的指导

    我终于也掌握BFS啦

    哈哈哈哈

    展开全文
  • 百度地图API详解之自定义地图类型

    万次阅读 热门讨论 2013-01-03 16:38:31
    百度地图API目前默认支持两种地图类型(map type):普通图和维图,它们分别通过常量BMAP_NORMAL_MAP和BMAP_PERSPECTIVE_MAP来表示,在1.2版本中这两个常量实际上是MapType对象的实例。当然开发者也可以自己实例化...

    今天的文章主要介绍如何利用地图API实现自定义地图。

    百度地图API目前默认支持两种地图类型(map type):普通图和三维图,它们分别通过常量BMAP_NORMAL_MAP和BMAP_PERSPECTIVE_MAP来表示,在1.2版本中这两个常量实际上是MapType对象的实例。当然开发者也可以自己实例化一个MapType从而实现一个自定义的地图。

    切图工具的使用

    我们先从切图工具的使用开始,接着再分析该工具产生的代码来详细了解自定义地图的方法。切图工具放在了github上,具体地址为:https://github.com/jiazheng/BaiduMapTileCutter,进入后请下载TileCutter.exe:

    注意,该工具是基于.NET平台开发的,所以要求有.NET Framework 4 以上的版本。

    启动这个exe后会出现这个界面:

    首先我们要做的就是选择一张图片作为地图的底图(图片下载自这里):

    点击下一步后需要设置输出的目录,这里我们直接选择桌面:

    继续下一步,这里要设置输出类型,我们使用默认值,即图块和相关代码都由工具生成:

    坐标设置我们使用默认值,即图片的中心点所在的位置。由于我们制作的是独立的地图类型,所以中心点设置为0, 0即可。

    级别范围设置:我们使用自定义,将范围设置为5到10级,原图放置在第10级,这样5到9级工具就会自动缩小图片。建议原图所在级别与最大级别一致,否则高于原图所在级别的时候图片会发虚(因为工具会将图片进行放大处理)。

    设置地图类型的名称:

    一切就绪,最后可以确认所有的信息是否正确。然后就可以点击“开始切图”了。

    完成了:

    这时我们会发现桌面多了一个index.html和一个tiles文件夹。我们打开index.html会看到结果:

    源代码解析

    现在再来看看这个页面的代码部分:

    复制代码
    <!DOCTYPE html>
    <html>
    <head>
    <title>自定义地图类型</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="http://api.map.baidu.com/api?v=1.2"></script>
    </head>
    <body>
    <div id="map" style="width:800px;height:540px"></div>
    <script type="text/javascript">
    var tileLayer = new BMap.TileLayer();
    tileLayer.getTilesUrl = function(tileCoord, zoom) {
        var x = tileCoord.x;
        var y = tileCoord.y;
        return 'tiles/' + zoom + '/tile' + x + '_' + y + '.png';
    }
    var MyMap = new BMap.MapType('MyMap', tileLayer, {minZoom: 5, maxZoom: 10});
    var map = new BMap.Map('map', {mapType: MyMap});
    map.addControl(new BMap.NavigationControl());
    map.centerAndZoom(new BMap.Point(0, 0), 10);
    </script>
    </body>
    </html>
    复制代码

    代码先创建了一个TileLayer实例,它代表一个图层,接着实现getTilesUrl方法提供图片的路径。getTilesUrl方法由API在铺图的时候进行调用,调用时会提供图块编号和级别信息,开发者要做的就是根据图块编号和级别信息返回正确图片地址(有关坐标和图块编号的内容可以阅读此文)。

    下面代码创建一个MapType实例,第一个参数为地图类型的名字,第二个参数为地图类型所对应的图层,这里我们直接传递之前创建的TileLayer实例,后面是一些可选的配置参数,这里指定了最小级别和最大级别。

    后面的代码就很简单了,创建map实例,并通过配置参数指定地图类型为MyMap。

    如果大家有月球或火星的图片,那么创建一个月球地图或者火星地图也就不是一件难事了。

    展开全文
  • GP服务的输入输出参数数据类型

    千次阅读 2013-06-22 15:14:45
    GP服务的输入参数数据类型: 输入参数数据类型 在 ArcGIS Desktop 客户端上是否受支持? 在 ArcGIS Explorer 客户端上是否受支持? 在 Web 应用程序客户端上是否受支持? ...
  • Android开发笔记(一百零地图与定位SDK

    万次阅读 热门讨论 2016-06-01 14:32:44
    集成地图SDK 国内常用的地图SDK就是百度和高德了,二者的用法大同小异,可按照官网上的开发指南一步步来。下面是我在集成地图SDK时遇到的问题说明: 1、点击基本地图功能选项,不能打开地图,弹出“key验证出错!...
  • 地图绘图输出使用Map控件提供的属性和方法,学习本节前请先熟悉Map控件,重点掌握它的绘图属性和方法。2.8.1坐标系1 Map控件窗口坐标系Map控件窗口使用直角坐标系,以控件窗口的左上角为原点,向右是X轴,向下是Y轴...
  • 公司项目使用百度地图需要实现自定义框选区域后判断设备点是否在区域内,因用户自定义区域可能是圆型或者是多边形,就需要在用户用鼠标创建完自定义图形后判断图形的类型。 百度已经给出了用鼠标绘制各类覆盖物的...
  • 解决矢量地图与卫星地图叠加有偏移的两方法 1 概述 众所周知,谷歌地图除了在从国外服器下载的卫星地图以外,其它地图与实际坐标都是有偏移的。另外,如高德地图、雅虎地图、SOSO地图等同样存在坐标偏移的问题...
  • 、osmdroid离线地图瓦片使用

    千次阅读 2017-10-20 22:10:25
    支持的离线数据格式osmdroid支持多种不同类型的离线缓存瓦片。 sqlite数据库(osmdroid推荐) osmdroid ZIP MBTiles FEMF GeoPackage(开发中) 创建离线缓存瓦片你有多种不同的选择。OSM Map Tile Packager ( OSM...
  • 大疆精灵4航测输出正摄影和维模型教程

    万次阅读 多人点赞 2019-03-15 12:04:39
    随便拿台大疆四旋翼无人机,配上免费的第方航线规划软件,再用网上到处能下载的无人机影像处理软件,就能轻松生成正射影像和倾斜维模型。今天以大疆精灵系列无人机为例,主要介绍使用Pix4dCapture和Altizure软件...
  • 步,实现BDLocationListener接口: /** * 位置监听器 * * BDLocationListener接口有1个方法需要实现: 1.接收异步返回的定位结果,参数是BDLocation类型参数。 */ class MyLocationListener ...
  • Super Iservice 发布地图三维服务

    千次阅读 2018-08-01 16:10:55
    SuperMap Iservice 发布地图服务 发布地图流程图 如上图所示,我们有两种地图发布的途径,分别为使用桌面应用程序(idesktop)直接发布和使用Iserver发布。 一、使用idesktop发布Iserver Rest服务 ...
  • 本片博客主要介绍的是小程序利用百度地图搜索附近公里信息 开篇先提一下,网上有很多关于小程序搜索框的,地图地点信息检索的,路线导航的,以及一个找事吧APP模仿的小程序。我也看过这些内容,整理一下,就是...
  • 在玩游戏的时候,有些河流断崖等地方是不能通过的,高处...大家在开发游戏的时候,地图的结构类型不同,采用的障碍物判定一般也就不同,地图类型和障碍物检测联系密切,因此雾央会介绍一下不同地图类型可以采取的方法。
  • 1、GeoServer(地理信息系统服务器)是 OpenGIS Web 服务器规范的 J2EE 实现(geoserver...能够将网络地图输出为jpeg、gif、png、SVG、KML等格式;能够运行在任何基于 J2EE/Servlet 容器之上。其安装方式有两,一...
  • 数字栅格地图矢量化及维显示教程

    万次阅读 多人点赞 2018-04-22 14:31:19
    对等高线地形图扫描件在ArcMap中依次进行地理配准、地理要素矢量化、拓扑检查、等高线平滑、附高程值、生成TIN、在TIN间拉伸操作,在ArcScene中进行叠加遥感影像、浮动于自定义表面操作,最终得到一幅维地形图。...
  • 调数据库标准和输出表格

    千次阅读 2020-05-10 21:21:52
    地类图斑属性结构中删除了线状址物和零星地物相关属性字段, 增加了 “线性图斑宽度”、“图斑细化代码”、“图斑细化名称”"“耕地种植属性代码”、“耕地 植属性名称”、“耕地等别”、“城镇村属性码”和“数舞...
  • 定位+跟随+距离测量+地图自适应缩放
  • 1.Arcgis ArcEngine二次开发: 输出地图、宗地草图、权属协议书附图、房产分层分户图、公示图、调土地利用图、行政区划图、标准分幅图等各种图件 有需要联系QQ:185242573. 2.接AE二次开发,程序实现数据处理、...
  • Android App跳转百度地图、高德地图、腾讯地图进行目的地导航。 先放上百度、高德、腾讯地图调起API文档地址,有些参数不懂可以参考。 百度地图:http://lbsyun.baidu.com/index.php?title=uri/api/android 高德...
  • 1、开发背景 2、开发环境 2.1基础开发环境 2.2百度地图环境 2.3高德地图环境 2.4腾讯地图环境 3、工程配置 3.1 添加jar包 3.2 添加so文件 3.3 AndroidMainfest.xml配置 ...现在将市面上应用最广泛的家...
  • 地图定位技术揭秘()

    千次阅读 2018-11-16 13:12:07
    而定位技术在地图软件里的应用可谓无法替代,尤其是在小范围的室内定位环境下,如何帮助用户高精度搜索导航,是百度地图定位技术的研究重点。 我们一提到定位,大家印象中最熟悉的技术可能就是GPS定位。其实更为准确...
  • , user-scalable=no, width=device-...'>兴趣点:" + data.regeocode.pois[j].name + "</td><td>类型:" + data.regeocode.pois[j].type + "</td><td>距离:" + data.regeocode.pois[j].distance + "米</td></...
  • 软件实现地图引擎的研究

    千次阅读 2016-10-22 11:30:47
    写在前面: 这篇东西,本来写下来是想去投出版社的。...当前在许多导航类产品中地图引擎的使用已经很多见了,特别是随着近些年硬件技术的发展,加上许多维的图形绘图软硬件库的支持,使得地图

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 36,073
精华内容 14,429
关键字:

地图输出的三种类型