Winform allows you to read and display Shp-raster graphics files (and store shp to WKB format in oracle) with source code,
During the GIS Spatial Database Course Design last semester, the teacher asked to read and display Shp-raster graphics files, and stored shp to WKB in oracle format without using third-party class libraries, it took a day to find some information on the Internet to display a simple Raster Graphic File.
Sometimes we know the storage format of a file, so we can write a program to easily read the desired data. During reading, we naturally need to use system. IO to operate IO streams. In this demonstration, the map vector data (actually reading some vertices, lines, and surface coordinate information) is read and visualized. Start to enter the subject.
0. demonstration of results
Basic display
Coordinate reading
1. What is a shp file?
The shape file is developed by ESRI. An ESRI (Environmental Systems Research Institute) shape file includes a master file, an index file, and a dBASE table. The suffix of the master file is. shp.
2. shp File Format
Baidu Library
(This document is also available in the root directory of the shared program-shp.txt)
3. Shared program Parsing
(1) What I/O class is used for reading the data first (Chinese Vector shp data is available in the shared folder. If you are interested, open it)
BinaryReader reads the base metadata type as a binary value using a specific encoding. (Note: files are read in the form of streams. If some bytes are not useful in your program
To ensure that the file stream continues)
Private void ReadFile (string filePath) {using (var reader = new StreamReader (filePath) {using (var br = new BinaryReader (reader. baseStream) {// read the header file readerHead. readFileHead (br );}}} /// <summary> /// read the shp File Header class // </summary> public class ReaderHead {// actual length of the File Integer big public int FileLength {get; set;} // version 1000 Integer Little public int FileBanben {get; set ;} // ry type indicates the geometric type of the space data recorded in the Shapefile Integer Little public int ShapeType {get; set ;} // The minimum value of the X direction in the space occupied by Xmin space data is Double Little public double Xmin {get; set ;} // maximum value of the space occupied by Ymax space data in the Y direction Double Little public double Ymax {get; set ;} // The maximum value of X in the range of space occupied by Xmax space. Double Little public double Xmax {get; set ;} // The minimum value of the space occupied by Ymin space data in the Y direction is Double Little public double Ymin {get; set ;} // The minimum value of the X direction in the space occupied by Zmin space data is Double Little public double Zmin {get; set ;} // maximum value of the space occupied by Zmax space data in the Y direction Double Little public double Zmax {get; set ;} // maximum X direction of the space occupied by Mmax space data Double Little public double Mmax {get; set ;} // The minimum value of the space occupied by Mmin space data in the Y direction Double Little public double Mmin {get; set ;} /// <summary> /// read the file header information /// </summary> /// <param name = "fileStream"> file stream </param> /// <returns> </returns> public void ReadFileHead (BinaryReader fileStream) {// File Reading Process // Remove Unused 24 bytes /// start position name numerical type order // 0 File Code 9994 Integer big // 4 Unused 0 Integer big // 8 Unused 0 Integer big // 12 Unused 0 Integer big // 16 Unused 0 Integer big // 20 Unused 0 Integer big fileStream. readBytes (24); // the actual length of the file. Integer big int FileLength = fileStream. readInt32 (); // 28 version 1000 Integer Little // <0 indicates the Data Length unknown int FileBanben = fileStream. readInt32 (); // 32 ry type indicates the geometric type of the space data recorded in this Shapefile File Integer Little ShapeType = fileStream. readInt32 (); // the minimum value of the X direction in the range of space occupied by data in 36 Xmin Double Little Xmin = fileStream. readDouble (); // 44 maximum value of Y direction in the range of space occupied by Ymax space data Double Little Ymax =-1 * fileStream. readDouble (); // 52 the maximum value of X in the space occupied by Xmax space; Double Little Xmax = fileStream. readDouble (); // the minimum value of the space occupied by 60 Ymin data in the Y direction. Double Little Ymin =-1 * fileStream. readDouble (); // 68 * Minimum Z-direction value of the space occupied by Zmin space data; Double Little Zmin = fileStream. readDouble (); // 76 * maximum value in Z direction of the space occupied by Zmax space data Double Little Zmax = fileStream. readDouble (); // 84 * Minimum Mmin Measure value Double Little Mmin = fileStream. readDouble (); // 92 * maximum Mmax Measure value Double Little Mmax = fileStream. readDouble ();}}
(2) According to the read file type (point? Line? Face ?) Read the coordinate information (continue reading the file stream ),
Switch (readerHead. ShapeType) {case (int) EnumShapeType. Point: // Clear the data points. Clear (); while (br. PeekChar ()! =-1) {Point point = Point. readerPoint (br); points. add (point) ;}// Save the read coordinate information to the local Txt file WriteTxtFile. writeTxtPoint (points, shpName); break; case (int) EnumShapeType. polyLine: // clear the previously opened data polylines. clear (); while (br. peekChar ()! =-1) {Polyline polyline = Polyline. readerPolyline (br); polylines. add (polyline);} // Save the read coordinate information to the WriteTxtFile in the local Txt file. writeTxtPolyline (polylines, shpName); break; case (int) EnumShapeType. polygon: // clear the last opened data polygons. clear (); while (br. peekChar ()! =-1) {Polygon polygon = Polygon. readerPolygon (br); polygons. add (polygon);} // Save the read coordinate information to the WriteTxtFile in the local Txt file. writeTxtPolygon (polygons, shpName); break ;}
Take the reading line as an example (in simple words, many lines are divided into one line and stored one by one point .)
Public class Polyline // line class {public double [] Box {get; set;} // represents the number of child segments that constitute the current line target public int NumParts {get; set ;} // indicates the number of coordinate points included in the current line target. public int NumPoints {get; set;} // file type: public int ShpType {get; set ;} public List <int> Parts {get; set;} // index of the first vertex in the section public List <Point> Points {get; set ;} // All parts of the vertex public Polyline () {Box = new double [4];} public static Polyline ReaderPolyline (BinaryReader br) {var po Lyline = new Polyline (); polyline. parts = new List <int> (); polyline. points = new List <Point> (); // the Content of the object information Record header contains two Record items: Record Number and coordinate Record Length. Uint RecordNum = br. readUInt32 (); int DataLength = br. readInt32 (); // read the I-th record // ry type polyline. shpType = br. readInt32 (); // The coordinate range (Box) indicates that the coordinate range of the current line target is double 32 4 Little for (int I = 0; I <4; I ++) {polyline. box [I] = br. readDouble ();} // The number of child segments (NumParts) indicates the number of child segments that constitute the current line target. int type 4 1 Little polyline. numParts = br. readInt32 (); // Number of coordinate points (NumPoints) indicates the number of coordinate points included in the current line target. int type 4 1 Little polyline. numPoints = br. readInt32 (); // The Parts Array records the coordinates of each child line segment in the starting position of the Points array. int type 4× NumParts Little for (int I = 0; I <polyline. numParts; I ++) {var parts = new int (); parts = br. readInt32 (); polyline. parts. add (parts);} // The Points Array records all coordinate information. The Point type determines NumPoints Little for (int j = 0; j <polyline. numPoints; j ++) {var pointtemp = new Point (); pointtemp. X = br. readDouble (); pointtemp. Y =-1 * br. readDouble (); polyline. points. add (pointtemp) ;}return polyline ;}}
(3) visual display of Files
To draw and display in the form, use using System. Drawing to draw both GDI +. The key to drawing is to find the largest rectangle in the visible range and draw all the data into the form.
You can see this information, Xmin Ymax Xmax Ymin, so that I can calculate the visible range.
Double width = readerHead. xmax-readerHead. xmin; double height = readerHead. ymax-readerHead. ymin; showShp. zooX = (float) (panel1.Width * 0.9/width); // X-axis magnification showShp. zooY = (float) (panel1.Height * 0.9/height); // y-axis magnification
Draw a graph in panelease paint
Private void panelappspaint (object sender, PaintEventArgs e) {// display the current file e. graphics. drawString ("current file:" + shpName, Font, Brushes. blue, new PointF (350, 0); switch (readerHead. shapeType) {case (int) EnumShapeType. point: // Point type foreach (Point p in points) {// convert to float type PointF pp = ShowShp. toPointF (p, readerHead. xmin, readerHead. ymin, showShp. zooX, showShp. zooY); e. graphics. drawEllipse (pen, pp. x, pp. y, 1.5f, 1.5f);} break; case (int) EnumShapeType. polyLine: // line type foreach (Polyline p in polylines) {// used to generate line PointF [] pointFsx = ShowShp. toPointFs (p, readerHead. xmin, readerHead. ymin, showShp. zooX, showShp. zooY); e. graphics. drawLines (pen, pointFsx);} break; case (int) EnumShapeType. polygon: // surface type // used to generate line foreach (Polyline p in polygons) {PointF [] pointFsm = ShowShp. toPointFs (p, readerHead. xmin, readerHead. ymin, showShp. zooX, showShp. zooY); e. graphics. drawLines (pen, pointFsm); e. graphics. fillPolygon (Brushes. pink, pointFsm) ;}break ;}}
(4) read coordinate information
This is relatively simple. Point data is stored during file reading. If you are interested, refer to the source code. Let's take a look at the coordinate structure,
Independent coordinate points:
517336.983662845, 2860942.68850762
517445.323959293, 2860897.87513047
Line coordinate:
Line 1:
-431977923441.66, 197606922425.44, 0
-3676407859.07796, 46874200203.2439, 0
Line 2:
-295950832655.775,-179224883130.05, 0
112130439701.878,-50550608062.3219, 0
Line 3:
-338229523035.172,-919101964.769489, 0
294112628726.236, 13786529471.5423, 0
Surface coordinates (actually the first and end sides ):
Polygon 2:
517494.301149368, 2861056.80072212, 0
517492.347002029, 2861056.61300087, 0
517491.879999161, 2861058.99200249, 0
517493.744001389, 2861059.31100273, 0
517494.301149368, 2861056.80072212, 0
Polygon 3:
517496.790002823, 2861099.2650013, 0
517495.791894913, 2861099.20348549, 0
517495.546682358, 2861103.18202782, 0
517496.544790268, 2861103.24354362, 0
517496.790002823, 2861099.2650013, 0
Polygon 4:
517512.920000076, 2861099.54700279, 0
517499.350999832, 2861097.9810009, 0
517499.047838211, 2861100.16797829, 0
517512.573999405, 2861102.04300117, 0
517512.920000076, 2861099.54700279, 0
(5) source code parsing
The structure should be quite obvious, so I will not explain it much. shp is converted to the WKB (OGC well-known binary) format and stored in oracle. The oracle connection configuration file is stored in the App. under config, there is not much explanation about the shp to WKB format stored in oracle. It is professional. If you have knowledge of GIS, you can refer to it.
If you have any questions, please leave me a message or make any mistakes. Thank you !!!
Source Code address: http://pan.baidu.com/s/1boInPIR (including China vector map data)