shp地图解析(不用AE)

AE太重型,还收费,如果只是加载地图作为底图,可以用纯C#实现。

总体架构

文件头
记录头记录内容
记录头记录内容
。。。。。。。。。。。。
记录头记录内容

文件头

位置 类型 字段 说明
Byte 0 int File Code 文件代码
Byte 4 int 无用  
Byte 8 int 无用  
Byte 12 int 无用  
Byte 16 int 无用  
Byte 20 int 无用  
Byte 24 int File Length 文件长度
Byte 28 int Version 版本
Byte 32 int Shape Type 图形类型1:Point,点类型3:PolyLine,线类型5:Polygon,面类型
Byte 36 double Xmin 整图的X轴坐标最小值
Byte 44 double Ymin 整图的Y轴坐标最小值
Byte 52 double Xmax 整图的X轴坐标最大值
Byte 60 double Ymax 整图的Y轴坐标最大值
Byte 68* double Zmin  
Byte 76* double Zmax  
Byte 84* double Mmin  
Byte 92* double Mmax  

记录头

位置 类型 字段 说明
Byte 0 int Record Number 记录号,从1开始
Byte 4 int Content Length 内容长度,内容的16位字数,不包括记录号。

记录内容

位置 类型 字段 说明
Byte 0 int ShapeType Shape类型
Byte 4 double [4] Box 该线条的边界盒,以Xmin,Ymin,Xmax,Ymax的顺序存储
Byte 36 int NumParts 是PolyLine中部分的数目
Byte 40 int NumPoints 是PolyLine中的数目
Byte 44 int [NumParts] Parts 每条PolyLine存储它在点数列中的第一个点的索引。数列索引是从0开始的。Parts[NumParts]数组是Points[NumPoints]数组的目录
X Point[NumPoints] Points 本条记录的所有点。Struct Point {Double  X;Double  Y;}

PartsPoints之间的关系:

如果Parts [0]=0Parts [1]=3Parts [2]=11Parts [3]=15那么

第0条线:(Points[0], Points[1] , Points[2])三个点依次连结

第1条线:(Points[3], Points[4] , Points[5] , Points[6] , Points[7] , Points[8] , Points[9] , Points[10])这几个点依次连结

第3条线:(Points[11], Points[12] , Points[13] , Points[14])三个点依次连结

ClassShp类:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.IO;

namespace SDD
{struct StructShapePoint
    {
        public double X;
        public double Y;
    }

    struct StructShapePolyline
    {
        public int RecordNumber;//记录号
        public int ContentLength;//内容长度
        public int ShapeType;
        public double[] Box;//长度为4
        public int PartsCount;
        public int PointsCount;
        public List<int> Parts;//在部分中第一个点的索引
        public List<StructShapePoint> Points;//所有部分的点
        public List<StructShapePoint[]> Lines;//把点按线组织好
    }

    class ClassShp
    {
        public string FileName;
        public int FileLength;
        public int FileVersion;
        public int ShapeType;//绘图类型:1-点,3-线,5-面
        public double Xmin, Ymin, Xmax, Ymax;//地图边界尺寸
        public double RawWidth, RawHeight;//地图大小,原始值
        public double RawCenterX, RawCenterY;//shp原始坐标系的中心点
        public List<StructShapePoint> ListPoints = new List<StructShapePoint>();//点集合
        public List<StructShapePolyline> ListPolylines = new List<StructShapePolyline>();//线集合

        public double Scale = 0;//放大倍数,原始数据中1表示的像素数
        public double CenterX, CenterY;//地图缩放后的中心点在控件坐标系中的位置

        public double WindowWidth;//显示控件大小
        public double WindowHeight;

        public Bitmap Bmp = null;//用于显示的画布,大小等于显示控件
        public Pen ThePen = new Pen(Color.White, 1);

        public ClassShp()
        { }

        public ClassShp(string pmtShpPathName, double pmtVisibleWidth, double pmtVisibleHeight)
        {
            if (File.Exists(pmtShpPathName) == false) return;
            if (Init(pmtShpPathName, pmtVisibleWidth, pmtVisibleHeight))
            {
                SaveAsTxt(); //把数据保存成文本文档
            }
        }

        //################################################################################
        // 由Xmin等四个值计算出基本成员参数
        //################################################################################
        public void SetBaseParameter(double pmtXmin,double pmtYmin,double pmtXmax,double pmtYmax)
        {
            Xmin = pmtXmin;
            Ymin = pmtYmin;
            Xmax = pmtXmax;
            Ymax = pmtYmax;

            RawWidth = Xmax - Xmin;
            RawHeight = Ymax - Ymin;
            RawCenterX = (Xmin + Xmax) / 2;
            RawCenterY = (Ymin + Ymax) / 2;

            CenterX = WindowWidth / 2;
            CenterY = WindowHeight / 2;

            SetRelativityScale(1, WindowWidth, WindowHeight);

            Console.WriteLine("绘图类型:{0}", ShapeType);
            Console.WriteLine("地图边界:({0}, {1}), ({2}, {3})", Xmin, Ymin, Xmax, Ymax);
            Console.WriteLine("地图大小:{0} * {1}", RawWidth, RawHeight);
            Console.WriteLine("地图中心:({0}, {1})", RawCenterX, RawCenterY);
        }

        //################################################################################
        // 初始化
        //################################################################################
        public bool Init(string pmtShpPathName, double pmtVisibleWidth, double pmtVisibleHeight)
        {
            if (File.Exists(pmtShpPathName) == false) return false;

            int nameIndex = pmtShpPathName.LastIndexOf("\\")+1;
            int nameLenght = pmtShpPathName.Length-5-pmtShpPathName.LastIndexOf("\\");

            FileName = pmtShpPathName.Substring(nameIndex, nameLenght);

            WindowWidth = pmtVisibleWidth;
            WindowHeight = pmtVisibleHeight;

            try
            {
                FileStream fs = new FileStream(pmtShpPathName, FileMode.Open);
                BinaryReader br = new BinaryReader(fs, Encoding.Default);

                br.ReadBytes(24);
                FileLength = br.ReadInt32();
                FileVersion = br.ReadInt32();
                ShapeType = br.ReadInt32();

                Xmin = br.ReadDouble();
                Ymin = br.ReadDouble();
                Xmax = br.ReadDouble();
                Ymax = br.ReadDouble();

                br.ReadBytes(32);

                if (ShapeType == 1)
                {
                    ListPoints.Clear();
                    while (br.PeekChar() != -1)
                    {
                        StructShapePoint shapePoint = new StructShapePoint();
                        uint recordNum = br.ReadUInt32();
                        int dataLength = br.ReadInt32();
                        br.ReadInt32();
                        shapePoint.X = br.ReadDouble();
                        shapePoint.Y = br.ReadDouble();
                        ListPoints.Add(shapePoint);
                    }
                }//end of : if (ShpType==1)
                else if (ShapeType == 3 || ShapeType == 5)
                {
                    ListPolylines.Clear();
                    while (br.PeekChar() != -1)
                    {
                        StructShapePolyline shapePolyline = new StructShapePolyline();
                        shapePolyline.Box = new double[4];
                        shapePolyline.Parts = new List<int>();
                        shapePolyline.Points = new List<StructShapePoint>();
                        shapePolyline.Lines = new List<StructShapePoint[]>();
                        shapePolyline.RecordNumber = br.ReadInt32();
                        shapePolyline.ContentLength = br.ReadInt32();
                        shapePolyline.ShapeType = br.ReadInt32();
                        shapePolyline.Box[0] = br.ReadDouble();
                        shapePolyline.Box[1] = br.ReadDouble();
                        shapePolyline.Box[2] = br.ReadDouble();
                        shapePolyline.Box[3] = br.ReadDouble();
                        shapePolyline.PartsCount = br.ReadInt32();
                        shapePolyline.PointsCount = br.ReadInt32();

                        //把每一段线的开始点偏移读进Parts队列
                        for (int i = 0; i < shapePolyline.PartsCount; i++)
                        {
                            int tmpPart = br.ReadInt32();
                            shapePolyline.Parts.Add(tmpPart);
                        }
                        //把所有点读进Points队列
                        for (int i = 0; i < shapePolyline.PointsCount; i++)
                        {
                            StructShapePoint tmpPoint = new StructShapePoint();
                            tmpPoint.X = br.ReadDouble();
                            tmpPoint.Y = br.ReadDouble();
                            shapePolyline.Points.Add(tmpPoint);
                        }
                        //把该线的点读进Lines队列
                        for (int i = 0; i < shapePolyline.PartsCount; i++)
                        {
                            int startpoint;
                            int endpoint;

                            if (i == shapePolyline.PartsCount - 1)
                            {
                                startpoint = (int)shapePolyline.Parts[i];
                                endpoint = shapePolyline.PointsCount;
                            }
                            else
                            {
                                startpoint = (int)shapePolyline.Parts[i];
                                endpoint = (int)shapePolyline.Parts[i + 1];
                            }
                            StructShapePoint[] shpPointArray = new StructShapePoint[endpoint - startpoint];
                            for (int j = 0, k = startpoint; k < endpoint; j++, k++)
                            {
                                shpPointArray[j].X = shapePolyline.Points[k].X;
                                shpPointArray[j].Y = shapePolyline.Points[k].Y;
                            }
                            shapePolyline.Lines.Add(shpPointArray);
                        }
                        //把该线条加进m_polylines队列
                        ListPolylines.Add(shapePolyline);
                    }
                }//end of : else if (ShpType == 3)
                SetBaseParameter(Xmin, Ymin, Xmax, Ymax);
                return true;
            }
            catch (System.Exception ex)
            {
                Console.WriteLine("异常:ClassShp.Init()" + ex.ToString());
                return false;
            }
        }

        //################################################################################
        // 把数据写成txt文本
        //################################################################################
        public void SaveAsTxt()
        {
            StreamWriter swLine = new StreamWriter(FileName+".txt");
            swLine.WriteLine("绘图类型:{0}", ShapeType);
            swLine.WriteLine("地图边界:({0}, {1}), ({2}, {3})", Xmin, Ymin, Xmax, Ymax);
            swLine.WriteLine("地图大小:{0} * {1}", RawWidth, RawHeight);
            swLine.WriteLine("地图中心:({0}, {1})", RawCenterX, RawCenterY);

            int recordCount = 0;
            if (ShapeType==1)
            {
                foreach (StructShapePoint p in ListPoints)
                {
                    swLine.WriteLine("点{0}:    ({1},    {2})", recordCount, p.X, p.Y);
                    recordCount++;
                }
            }
            else if (ShapeType==3 || ShapeType==5)
            {
                foreach (StructShapePolyline p in ListPolylines)
                {
                    for (int i = 0; i < p.Lines.Count; i++)
                    {
                        swLine.WriteLine("记录内容{0}:########################################################", recordCount, i);
                        for (int j = 0; j < p.Lines[i].Length; j++)
                        {
                            StructShapePoint ps = p.Lines[i][j];
                            swLine.WriteLine("线{0}:    ({1},    {2})", j, ps.X, ps.Y);
                        }
                    }
                    recordCount++;
                }//end of :foreach
            }
            swLine.Close();
        }

        //################################################################################
        // 把图绘进Bmp中
        //################################################################################
        public bool DrawBmp(int pmtWidth, int pmtHeight)
        {
            double screenWidth = RawWidth * Scale;
            double screenHeight = RawHeight * Scale;

            try
            {
                Bmp = new Bitmap(pmtWidth, pmtHeight);//创建画布
                Graphics g = Graphics.FromImage(Bmp);

                g.TranslateTransform((float)0, (float)pmtHeight);//变换坐标系,把左下角置为原点
                g.ScaleTransform((float)1, (float)-1);

                if (ShapeType == 1) //点类型
                {
                    foreach (StructShapePoint p in ListPoints)
                    {
                        PointF pf = new PointF();
                        double offsetX = CenterX - screenWidth / 2.0;
                        double offsetY = CenterY - screenHeight / 2.0;
                        pf.X = (float)((p.X - Xmin) * Scale + offsetX);
                        pf.Y = (float)((p.Y - Ymin) * Scale + offsetY);
                        float r = 3;
                        //g.DrawEllipse(ThePen, pf.X - r / 2, pf.Y + r / 2, r * 2, r * 2);//画点
                        Brush bs = new SolidBrush(Color.Green);//填充的颜色
                        g.FillEllipse(bs, pf.X - r / 2, pf.Y + r / 2, r * 2, r * 2);
                    }
                }
                else if (ShapeType == 3 || ShapeType == 5) //线类型和面类型是一样的
                {
                    //Console.WriteLine("线类型");
                    foreach (StructShapePolyline p in ListPolylines)
                    {
                        for (int i = 0; i < p.Lines.Count; i++)
                        {
                            PointF[] pfArray = new PointF[p.Lines[i].Length];
                            for (int j = 0; j < p.Lines[i].Length; j++)
                            {
                                StructShapePoint ps = p.Lines[i][j];
                                double offsetX = CenterX - screenWidth / 2.0;
                                double offsetY = CenterY - screenHeight / 2.0;
                                pfArray[j].X = (float)((ps.X - Xmin) * Scale + offsetX);
                                pfArray[j].Y = (float)((ps.Y - Ymin) * Scale + offsetY);
                            }
                            g.DrawLines(ThePen, pfArray);
                        }
                    }
                }        return true;
            }
            catch (System.Exception ex)
            {
                Console.WriteLine("异常:ClassShp.drawBmp" + ex.ToString());
                return false;
            }
        }
    }
}

在主窗口放置一个pictureBox控件,名为pictureBoxMap.

主函数:

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

namespace SDD
{
    public partial class FormMain : Form
    {
        ClassShp ShapeChina;

        public FormMain()
        {
            InitializeComponent();

            string mapChinaPathName = new ClassShp(@"D:\map\地图\国界.shp", pictureBoxMap.Width, pictureBoxMap.Height);
            pictureBoxMap.Refresh();
        }
        private void pictureBoxMap_Paint(object sender, PaintEventArgs e)
        {
            Bitmap bmp = new Bitmap(pictureBoxMap.Width, pictureBoxMap.Height);//创建画布
            ShapeChina.DrawBmp(pictureBoxMap.Width, pictureBoxMap.Height);
            e.Graphics.DrawImage(ShapeChina.Bmp, 0, 0);
        }
    }
}
时间: 2024-12-12 16:46:19

shp地图解析(不用AE)的相关文章

全国SHP地图数据赠送

百度搜索:GIS之家获取全国SHP图层数据的方式:收藏(ArcGIS地图全国电子地图shp格式版本GIS地图数据.GIS开发顺德政府GIS公共服务共享平台),并且截图验证,验证通过后,收下邮箱,我把下载链接发到你们的邮箱:地图数据坐标系为wgs1984,SHP地图数据图层信息目录如下:

LocationCoder 地图经纬度解析

LocationCoder 地图经纬度解析 其实,在地图里面将地图解析成有意义的地址,或者把地址转换成有意义的经纬度都是很容易的事情,只是我将其封装了支持KVO,通知中心,block取结果,代理取结果而已. 能通过组合的方式来封装对象扩展功能就绝对不会用继承的方式来扩展功能,只有当组合解决不了问题时才会使用继承:). 源码: LocationCoder.h + LocationCoder.m // // LocationCoder.h // // http://home.cnblogs.com/

使用highmaps制作中国地图

Highmaps 所需文件 http://code.highcharts.com/maps/highmaps.js(地图渲染的核心文件 必须引用)http://code.highcharts.com/maps/modules/data.js(地图数据拼接及解析的核心文件 必须引用)http://code.highcharts.com/maps/modules/drilldown.js(地图 展开明细的核心插件,若需要点击显示省市则需要引用,反之则不需要引用)http://sandbox.runj

使用R画地图数据

用R画地图数据 首先,从这里下载中国地图的GIS数据,这是一个压缩包,完全解压后包含三个文件(bou2_4p.dbf.bou2_4p.shp和bou2_4p.shx),将这三个文件解压到同一个目录下. 用R绘制地图比较简单.比如画一下全国范围的区域,可以用如下代码: library(maptools) mydat = readShapePoly("china-province-border-data.tar/china/bou2_4p.shp") #地图包位置,根据自己的角标位置设置

让isis支持高德地图

概述 由于项目需要用到地图,虽然isis的插件库里有个现成的地图实现,不过用的google地图,虽然google地图可以不用注册Appkey,但完全打不开.所以打算改成国产地图. 效果 先看下运行效果. 列表中的效果: 整体效果: 详细效果: 实现思路 高德地图的API跟Google地图类似,编程模型也相同,甚至很多类的命名都一样的.所以,从Google迁到高德还是比较容易的. 高德跟Google一样,用一个DIV来渲染地图.根据Vicket的编程方式,这个Div使用一个组件来表示,这个组件包含

SQL Server 2008空间数据应用系列十一:提取MapInfo地图数据中的空间数据解决方案

原文:SQL Server 2008空间数据应用系列十一:提取MapInfo地图数据中的空间数据解决方案 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Server 2008 R2调测. 2.具备 Transact-SQL 编程经验和使用 SQL Server Management Studio 的经验. 3.熟悉或了解Microsoft SQL Server 2008中的空间数据类型. 4.具备相应(比如OGC规范.KML规范)的GIS专业理论知识. 5

小程序地图导航功能实现(勾起使用外部高德或者腾讯地图)

原理就是:使用sdk 解析地址成经纬,再唤起小程序地图解析,然后通过这个选择使用外部的地图软件. 首先使用:先去下载腾讯地图sdk,将其引用. 第一步: var QQMapWX = require('../../map/qqmap-wx-jssdk.min.js'); const wxMap = new QQMapWX({ key: '*********' // 必填 }); 第二步:解析地址 //解析地址为经纬 detaiAddress: function (e) { var that = t

HTML5适合移动应用开发的几大特性

1.离线缓存为HTML5开发移动应用提供了基础 HTML5 Web Storage API可以看做是加强版的cookie,不受数据大小限制,有更好的弹性以及架构,可以将数据写入到本机的ROM中,还可以在关闭浏览器后再次打开时恢复数据,以减少网络流量. 同时,这个功能算得上是另一个方向的后台“操作记录”,而不占用任何后台资源,减轻设备硬件压力,增加运行流畅性. 在线app支持边使用边下载离线缓存,或者不下载离线缓存:而离线app必须是下载完离线缓存才能使用. 形象点说,cookie就是存了电话和菜

(转) 浅析HTML5在移动应用开发中的使用

(转)浅析HTML5在移动应用开发中的使用 (原)http://www.iteye.com/magazines/67 2012-03-07  来自 UECD.163.com  编辑 wangguo 有38498人浏览 收藏 html5 移动开发 app UI < > 猎头职位: 上海: Junior Product Manager 前言 HTML5的出现让移动平台的竞争由系统平台转向了浏览器之间:移动端的IE.Chrome.FireFox.Safari,亦或是新出现的浏览器,谁能达到在移动端对