SHP File Reading

Source: Internet
Author: User
Tags dbase

Friends who develop GIS may not be familiar with SHP, but they can see that csdn users are constantly asking questions about SHP files. In my spare time, I will summarize some knowledge about SHP files and share them with csdn users.

First, let's take a look at some simple knowledge about the SHP file.

Shapefile is a GIS File System Format File developed by the US Institute of Environmental Systems (ESRI). It is an industrial standard vector data file. Shapefile stores non-topological geometric objects and attribute information in the spatial feature table in the dataset. The geometric objects in the feature table are saved as graphical files represented by coordinate points set-SHP files, the shapefile file does not contain the topology data structure. A shape file contains three files: a main file (*. SHP), an index file (*. shx), and a DBASE (*. DBF) table. The main file is a directly accessed file with a variable length record. Each record Description forms the vertices coordinate values of a geographical feature. In the index file, each record contains the offset corresponding to the record of the master file starting from the header of the master file. The DBASE table contains the feature attributes of each feature in the SHP file, the one-to-one correspondence between geometric records and attribute data in a table is based on the number of records. The attribute records in the DBASE file must be in the same order as those in the main file. Graph data and attribute data establish a one-to-one correspondence relationship through the index number.

In shapefile, the coordinate file (. SHP) consists of a fixed-length file header and a subsequent variable-length space data record. The file header consists of 100 bytes of description information, which mainly describes the file length, shape type, and the range of the entire shape layer. The information constitutes the metadata of the spatial data. When importing spatial data, you must first read the file header to obtain the basic information of the Shape file, and then create the corresponding metadata table based on this information. The variable-length spatial data record is composed of a fixed-length record header and variable-length record content. Its record structure is basically similar, each record consists of a record header and record content (spatial coordinate pairs ). The record header contains two record items: Record Number and coordinate record length. The record numbers in the shapefile file start from 1, the length of a coordinate record is measured by 16 characters. The record content includes the target shapry type and the specific coordinate record (x, y). The record content varies with the specific content and format of the element ry type. Specific records include empty shape records, point records, line records, and polygon records.

The property file (. DBF) is used to record property information. It is a standard DBF file and consists of header files and entity information. The length of the file header is not long. It mainly describes the DBF File in general. The most important part is to describe the information of the record items of the DBF File in detail, for example, the name, data type, length, and other information of each record item are described in detail. The entity information part of the property file is an attribute record. Each record is composed of several record items. Therefore, you only need to read each record cyclically.

The index file (. shx) mainly contains the index information of the coordinate file. Each record in the file contains the offset of the corresponding coordinate file record from the file header of the coordinate file. The index file allows you to easily locate the coordinates of the specified target in the coordinate file. The index file consists of the file header and object information. The file header is a fixed length (100 bytes) record segment, and its content is basically the same as that of the coordinate file header. Its entity information is based on records. Each record contains two record items: Offset and content length.

Next let's look at the code (C ++ ):
SHP File Reading

Featureclass * cgismapdoc: importshapefiledata (File * fpshp, file * fpdbf) <br/>{< br/> // start when the SHP file header is read <br/> int filecode =-1; <br/> int filelength =-1; <br/> int version =-1; <br/> int shapetype =-1; <br/> fread (& filecode, sizeof (INT), 1, fpshp); <br/> filecode = reversebytes (filecode); </P> <p> If (filecode! = 9994) <br/>{< br/> cstring strtemp; <br/> strtemp. format ("Warning filecode % d", filecode); <br/> afxmessagebox (strtemp); <br/>}</P> <p> for (INT I = 0; I <5; I ++) <br/> fread (& filecode, sizeof (INT), 1, fpshp); </P> <p> fread (& filelength, sizeof (INT), 1, fpshp); <br/> filelength = reversebytes (filelength); </P> <p> fread (& version, sizeof (INT), 1, fpshp); <br/> fread (& shapetype, sizeof (INT), 1, fpshp); </P> <p> double temporiginx, temporiginy; <br/> fread (& temporiginx INX, sizeof (double), 1, fpshp ); <br/> fread (& temporiginy, sizeof (double), 1, fpshp); </P> <p> double xmaxlayer, ymaxlayer; <br/> fread (& xmaxlayer, sizeof (double), 1, fpshp); <br/> fread (& ymaxlayer, sizeof (double), 1, fpshp ); </P> <p> double * Skip = new double [4]; <br/> fread (Skip, sizeof (double ), 4, fpshp); <br/> Delete [] Skip; <br/> skip = 0; <br/> // read SHP file header end </P> <p> int uniqueid = This-> m_pdatasource-> getuniqueid (); <br/> featureclass * pshpdataset = 0; <br/> // create a dataset layer based on the target type. <Br/> switch (shapetype) <br/> {<br/> case 1: <br/> pshpdataset = (featureclass *) & (m_pdatasource-> createdataset (uniqueid, pointdataset, layername); <br/> break; <br/> case 3: <br/> case 23: <br/> pshpdataset = (featureclass *) & (m_pdatasource-> createdataset (uniqueid, linedataset, layername); <br/> break; <br/> case 5: <br/> pshpdataset = (featureclass *) & (m_pdatasource-> createdataset (Uniqueid, polygondataset, layername); <br/> break; <br/>}</P> <p> If (pshpdataset = 0) return 0; </P> <p> // read the DBF File Header --------- begin ------------ <br/> struct dbfheader <br/>{< br/> char m_nvalid; <br/> char m_adate [3]; <br/> char m_nnumrecords [4]; <br/> char m_nheaderbytes [2]; <br/> char m_nrecordbytes [2]; <br/> char m_nreserved1 [3]; <br/> char m_nreserved2 [13]; <br/> char m_nreserved3 [4]; <br/>} Dbfheader; </P> <p> struct dbffielddescriptor <br/> {<br/> char m_sname [10]; // It should be char m_sname [11] <br/> char m_ntype; <br/> char m_naddress [4]; <br/> char m_nfieldlength; <br/> char m_nfielddecimal; <br/> char m_nreserved1 [2]; <br/> char m_nworkarea; <br/> char m_nreserved2 [2]; <br/> char m_nsetfieldsflag; <br/> char m_nreserved3 [8]; <br/>}; </P> <p> fread (& dbfheader, sizeof (dbfheader), 1, fpdbf ); <br/>/* I NT recordsnum = * (int *) dbfheader. m_nnumrecords); <br/> int headlen = * (short *) dbfheader. m_nheaderbytes); <br/> int everyrecordlen = * (short *) dbfheader. m_nrecordbytes); </P> <p> If (recordsnum = 0 | headlen = 0 | everyrecordlen = 0) <br/> return 0; </P> <p> int fieldcount = (headlen-1-sizeof (dbfheader)/sizeof (dbffielddescriptor ); </P> <p> dbffielddescriptor * pfields = new dbffielddescriptor [FIE Ldcount]; <br/> for (I = 0; I <fieldcount; I ++) <br/> fread (& pfields [I], sizeof (dbffielddescriptor), 1, fpdbf); </P> <p> char endbyte; <br/> fread (& endbyte, sizeof (char), 1, fpdbf ); </P> <p> If (endbyte! = 0x0d) <br/>{< br/> Delete [] pfields; <br/> pfields = 0; <br/> return 0; <br/>}*/</P> <p> Fields & fields = pshpdataset-> getfields (); <br/> dbffielddescriptor field; <br/> byte endbyte = ''; <br/> char fieldname [12]; <br/> int fielddecimal, fieldlen, everyrecordlen = 0; <br/> while (! Feof (fpdbf) <br/>{< br/> fread (& endbyte, sizeof (byte), 1, fpdbf); <br/> If (endbyte = 0x0d) break; <br/> fread (& field, sizeof (dbffielddescriptor), 1, fpdbf); </P> <p> fieldname [0] = endbyte; <br/> for (I = 0; I <10; I ++) <br/> fieldname [I + 1] = field. m_sname [I]; <br/> fieldname [11] = '/0'; </P> <p> fielddecimal = field. m_nfielddecimal; <br/> fieldlen = field. m_nfieldlength; <br/> switch (field. m_ntype) <br/>{< Br/> case 'C': <br/> fields. addfield (fieldname, fieldname, field_string, fieldlen); <br/> break; <br/> case 'F': <br/> fields. addfield (fieldname, fieldname, field_double, fieldlen); <br/> break; <br/> case 'N ': <br/>{< br/> If (fielddecimal = 0) <br/> fields. addfield (fieldname, fieldname, field_int, fieldlen); <br/> else fields. addfield (fieldname, fieldname, field_double, fieldlen); <br/>}< br/> break; <br/>}< br/> E Veryrecordlen + = fieldlen; <br/>}< br/> // read the DBF File Header --------- end ------------ </P> <p> while (! Feof (fpshp) <br/>{< br/> // start of the read record header <br/> int recordnumber =-1; <br/> int contentlength =-1; <br/> fread (& recordnumber, sizeof (INT), 1, fpshp); <br/> fread (& contentlength, sizeof (INT), 1, fpshp ); <br/> recordnumber = reversebytes (recordnumber); <br/> contentlength = reversebytes (contentlength ); <br/> // The End Of The read record header </P> <p> switch (shapetype) <br/> {<br/> case 1: // '/001' <br/> // start when the point objective is read <br />{< Br/> Fields & featurefields = pshpdataset-> getfields (); <br/> feature * pfeature = new feature (recordnumber, 1, & featurefields ); </P> <p> int pointshapetype; <br/> fread (& pointshapetype, sizeof (INT), 1, fpshp); <br/> double xvalue, yvalue; <br/> fread (& xvalue, sizeof (double), 1, fpshp); <br/> fread (& yvalue, sizeof (double), 1, fpshp ); </P> <p> geopoint * pnewgeopoint = new geopoint (xva Lue, yvalue); <br/> pfeature-> setbound (xvalue, yvalue, 0, 0); <br/> pfeature-> setgeometry (pnewgeopoint ); <br/> This-> loadattributedata (pfeature, fpdbf, everyrecordlen); <br/> pshpdataset-> addrow (pfeature); <br/>}< br/> break; <br/> // end of reading a point objective </P> <p> case 3: // '/003' <br/> // start of the read line target <br/> {<br/> Fields & featurefields = pshpdataset-> getfields (); <br/> feature * pfeature = new feature (recordnumb Er, 1, & featurefields); </P> <p> int arcshapetype; <br/> fread (& arcshapetype, sizeof (INT), 1, fpshp ); </P> <p> double objminx, objminy, objmaxx, objmaxy; <br/> fread (& objminx, sizeof (double), 1, fpshp ); <br/> fread (& objminy, sizeof (double), 1, fpshp); <br/> fread (& objmaxx, sizeof (double), 1, fpshp ); <br/> fread (& objmaxy, sizeof (double), 1, fpshp); </P> <p> geopolyline * pnewgeoline = New geopolyline (); <br/> double width = objmaxx-objminx; <br/> double height = objmaxy-objminy; <br/> pfeature-> setbound (objminx, objminy, width, height); </P> <p> int numparts, numpoints; <br/> fread (& numparts, sizeof (INT), 1, fpshp ); <br/> fread (& numpoints, sizeof (INT), 1, fpshp ); <br/> // store the start index of each line <br/> int * startofpart = new int [numparts]; <br/> for (INT I = 0; I <numparts; I ++) <br/>{< br/> int indexfirstpoint; <br/> fread (& indexfirstpoint, sizeof (INT), 1, fpshp ); <br/> startofpart [I] = indexfirstpoint; <br/>}</P> <p> // handle the problem that a single target has multiple lines <br/> pnewgeoline-> setpointscount (numparts ); </P> <p> for (I = 0; I <numparts; I ++) <br/>{< br/> geopoints & points = pnewgeoline-> getpoints (I); <br/> int curposindex = startofpart [I]; <br/> int nextposindex = 0; <br/> Int curpointcount = 0; <br/> if (I = numparts-1) <br/> curpointcount = numpoints-curposindex; <br/> else <br/> {<br/> nextposindex = startofpart [I + 1]; <br/> curpointcount = nextposindex-curposindex; <br/>}< br/> points. setpointcount (curpointcount); <br/> // load the coordinates of a line segment <br/> for (INT iteratorpoint = 0; iteratorpoint <curpointcount; iteratorpoint ++) <br/>{< br/> double X, Y; <Br/> fread (& X, sizeof (double), 1, fpshp); <br/> fread (& Y, sizeof (double), 1, fpshp ); <br/> geopoint newvertex (x, y); <br/> points. setpoint (iteratorpoint, newvertex); <br/>}< br/> Delete [] startofpart; <br/> startofpart = 0; <br/> pfeature-> setgeometry (pnewgeoline); <br/> This-> loadattributedata (pfeature, fpdbf, everyrecordlen); <br/> pshpdataset-> addrow (pfeature ); <br/>}< br/> Break; <br/> // end of the read line target </P> <p> case 5: // '/00' <br/> // start of the read target <br/> {<br/> Fields & featurefields = pshpdataset-> getfields (); <br/> feature * pfeature = new feature (recordnumber, 1, & featurefields); <br/> int polygonshapetype; <br/> fread (& polygonshapetype, sizeof (INT ), 1, fpshp); <br/> If (polygonshapetype! = 5) <br/> afxmessagebox ("error: Attempt to load non Polygon Shape as polygon. "); </P> <p> double objminx, objminy, objmaxx, objmaxy; <br/> fread (& objminx, sizeof (double), 1, fpshp ); <br/> fread (& objminy, sizeof (double), 1, fpshp); <br/> fread (& objmaxx, sizeof (double), 1, fpshp ); <br/> fread (& objmaxy, sizeof (double), 1, fpshp); </P> <p> geopolygon * pnewgeopolygon = new geopolygon (); <br/> double width = objmaxx-objminx; <br/> double height = objmaxy-objminy; <br/> pfeature-> setbound (objminx, objminy, width, height ); </P> <p> int numparts, numpoints; <br/> fread (& numparts, sizeof (INT), 1, fpshp); <br/> fread (& numpoints, sizeof (INT), 1, fpshp); <br/> // store the start index of each surface <br/> int * startofpart = new int [numparts]; <br/> for (INT I = 0; I <numparts; I ++) <br/>{< br/> int indexfirstpoint; <br/> fread (& indexfirstpoint, sizeof (INT), 1, fpshp); <br/> startofpart [I] = indexfirstpoint; <br/>}</P> <p> // handle multiple problems with a single target <br/> pnewgeopolygon-> setpointscount (numparts ); </P> <p> for (I = 0; I <numparts; I ++) <br/>{< br/> geopoints & points = pnewgeopolygon-> getpoints (I); <br/> int curposindex = startofpart [I]; <br/> int nextposindex = 0; <br/> int curpointcount = 0; <br/> if (I = numparts-1) <br/> curpointcount = numpoints-curposindex; <br/> else <br/> {<br/> nextposindex = startofpart [I + 1]; <br/> curpointcount = nextposindex-curposindex; <br/>}< br/> points. setpointcount (curpointcount); <br/> // load the coordinates of a plane (polygon) <br/> for (INT iteratorpoint = 0; iteratorpoint <curpointcount; iteratorpoint ++) <br/>{< br/> double X, Y; <br/> fread (& X, sizeof (double), 1, fpshp ); <br/> fread (& Y, sizeof (double), 1, fpshp); <br/> geopoint newvertex (x, y); <br/> points. setpoint (iteratorpoint, newvertex); <br/>}< br/> Delete [] startofpart; <br/> startofpart = 0; <br/> pfeature-> setgeometry (pnewgeopolygon); <br/> This-> trim (pfeature, fpdbf, everyrecordlen); <br/> pshpdataset-> addrow (pfeature ); <br/>}< br/> break; <br/> // end of the read surface target </P> <p> case 23: // '/027' <br/> // read the start point of the measure line target <br/>{< br/> Fields & featurefields = pshpdataset-> getfields (); <br/> feature * pfeature = new feature (recordnumber, 1, & featurefields); <br/> int arcmshapetype; <br/> fread (& arcmshapetype, sizeof (INT ), 1, fpshp); </P> <p> double objminx, objminy, objmaxx, objmaxy; <br/> fread (& objminx, sizeof (double), 1, fpshp ); <br/> fread (& objminy, sizeof (double), 1, fpshp); <br/> fread (& objmaxx, sizeof (double), 1, fpshp ); <br/> fread (& objmaxy, sizeof (double), 1, fpshp); </P> <p> geopolyline * pnewgeoline = new geopolyline (); <br/> double width = objmaxx-objminx; <br/> double height = objmaxy-objminy; <br/> pfeature-> setbound (objminx, objminy, width, height ); </P> <p> int numparts, numpoints; <br/> fread (& numparts, sizeof (INT), 1, fpshp); <br/> fread (& numpoints, sizeof (INT), 1, fpshp); <br/> // stores the start index of each line <br/> int * startofpart = new int [numparts]; <br/> for (INT I = 0; I <numparts; I ++) <br/>{< br/> int indexfirstpoint; <br/> fread (& indexfirstpoint, sizeof (INT), 1, fpshp); <br/> startofpart [I] = indexfirstpoint; <br/>}</P> <p> // handle the problem that a single target has multiple lines <br/> pnewgeoline-> setpointscount (numparts ); </P> <p> for (I = 0; I <numparts; I ++) <br/>{< br/> geopoints & points = pnewgeoline-> getpoints (I); <br/> int curposindex = startofpart [I]; <br/> int nextposindex = 0; <br/> int curpointcount = 0; <br/> if (I = numparts-1) <br/> curpointcount = numpoints-curposindex; <br/> else <br/> {<br/> nextposindex = startofpart [I + 1]; <br/> curpointcount = nextposindex-curposindex; <br/>}< br/> points. setpointcount (curpointcount); <br/> // load the coordinates of a line segment <br/> for (INT iteratorpoint = 0; iteratorpoint <curpointcount; iteratorpoint ++) <br/>{< br/> double X, Y; <br/> fread (& X, sizeof (double), 1, fpshp ); <br/> fread (& Y, sizeof (double), 1, fpshp); <br/> geopoint newvertex (x, y); <br/> points. setpoint (iteratorpoint, newvertex); <br/>}< br/> Delete [] startofpart; <br/> startofpart = 0; </P> <p> double * value = new double [2 + numpoints]; <br/> fread (value, sizeof (double), 2 + numpoints, fpshp ); <br/> Delete [] value; <br/> value = 0; </P> <p> pfeature-> setgeometry (pnewgeoline ); <br/> This-> loadattributedata (pfeature, fpdbf, everyrecordlen); <br/> pshpdataset-> addrow (pfeature); <br/>}< br/> break; <br/> // read the end of the measure line target <br/>}< br/> return pshpdataset; <br/>}

In addition, I have a small program (C ++) reading the SHP file on hand. If you need a friend, please leave a mailbox. I will send it to you immediately

Reprint of friends please indicate the source: half smoke Ajie http://blog.csnd.net/gisfarmer

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.