📄 main.cs
字号:
using System;
using System.Runtime.InteropServices;
using System.Text;
using MapTools;
namespace NetTest
{
/// <summary>
/// A demonstration and test program for the use of
/// ShapeLib, a .NET wrapper class for the Shapefile C Library V1.2.10
/// </summary>
class Class1
{
const string FILENAME = "test";
const int NVERTICES = 11;
const int NFIELDS = 5;
const int NSHAPES = 3;
[STAThread]
static void Main(string[] args)
{
CreateSHP();
CreateDBF();
Console.WriteLine("\nPress any key to exit...");
Console.ReadLine();
}
private static void CreateSHP()
{
ShapeLib.ShapeType shpType = ShapeLib.ShapeType.Polygon;
Console.WriteLine("*****Creating {0}*****\n", ShapeLib.SHPTypeName(shpType));
IntPtr hShp;
double[] xCoord = new double[NVERTICES];
double[] yCoord = new double[NVERTICES];
// create an arbitrary geometric figure
// note that our boundary is defined clockwise, according
// to the ESRI shapefile rule that the neighborhood to the right
// of an observer walking along the ring in vertex order is
// the neighborhood inside the polygon. In contrast, holes are
// defined in counterclockwise order.
for (int i=0;i<NVERTICES;i++)
{
xCoord[i] = Math.Cos(Math.PI/5 * (double)i);
yCoord[i] = -Math.Sin(Math.PI/5 * (double)i);
}
// ensure start and end point are equal (some roundoff err occurs in Sin(2PI))
xCoord[NVERTICES-1]=xCoord[0];
yCoord[NVERTICES-1]=yCoord[0];
// create a new shapefile
hShp = ShapeLib.SHPCreate(FILENAME, shpType);
if (hShp.Equals(IntPtr.Zero))
return;
// add three shapes
IntPtr pshpObj = ShapeLib.SHPCreateSimpleObject(shpType, NVERTICES,
xCoord, yCoord, new double[NVERTICES]);
int iRet = ShapeLib.SHPWriteObject(hShp, -1, pshpObj);
ShapeLib.SHPDestroyObject(pshpObj);
// next shape will be 2 units to the right
for (int i=0;i<NVERTICES;i++)
xCoord[i] += 2;
pshpObj = ShapeLib.SHPCreateSimpleObject(shpType, NVERTICES,
xCoord, yCoord, new double[NVERTICES]);
iRet = ShapeLib.SHPWriteObject(hShp, -1, pshpObj);
ShapeLib.SHPDestroyObject(pshpObj);
// next will be 2 units up
for (int i=0;i<NVERTICES;i++)
yCoord[i] += 2;
// this polygon will have a triangular hole in its center,
// for the purpose of testing SHPCreateObject
double[] aX = new double[NVERTICES+4];
double[] aY = new double[NVERTICES+4];
double[] aZ = new double[NVERTICES+4];
double[] aM = new double[NVERTICES+4];
Array.Copy(xCoord, 0, aX, 0, NVERTICES);
Array.Copy(yCoord, 0, aY, 0, NVERTICES);
// center of polygon is at (2,2) - center our triangular hole there.
// Outer ring is defined clockwise; inner ring (hole) is defined ccwise
aX[NVERTICES] = 2.5;
aY[NVERTICES] = 2;
aX[NVERTICES+1] = 2;
aY[NVERTICES+1] = 2.5;
aX[NVERTICES+2] = 1.5;
aY[NVERTICES+2] = 1.5;
aX[NVERTICES+3] = aX[NVERTICES];
aY[NVERTICES+3] = aY[NVERTICES];
int[] apartStart = new int[2] {0, NVERTICES};
ShapeLib.PartType[] apartType =
new ShapeLib.PartType[2] {ShapeLib.PartType.Ring,ShapeLib.PartType.Ring};
pshpObj = ShapeLib.SHPCreateObject(shpType, -1, 2, apartStart, apartType, NVERTICES+4, aX, aY, aZ, aM);
iRet = ShapeLib.SHPWriteObject(hShp, -1, pshpObj);
ShapeLib.SHPDestroyObject(pshpObj);
// we want to test SHPOpen, so we will close hShp then reopen it
ShapeLib.SHPClose(hShp);
hShp = ShapeLib.SHPOpen(FILENAME, "rb+");
// get shape info and verify shapes were created correctly
double[] minB = new double[4];
double[] maxB = new double[4];
int nEntities=0;
ShapeLib.ShapeType shapeType = 0;
ShapeLib.SHPGetInfo(hShp, ref nEntities, ref shapeType, minB, maxB);
Console.WriteLine("Number Entries: {0}", nEntities);
Console.WriteLine("ShapeType: {0}", shapeType);
Console.WriteLine("Min XY: {0}, {1}", minB[0], minB[1]);
Console.WriteLine("Max XY: {0}, {1}", maxB[0], maxB[1]);
// test SHPReadObject on the first shape
int iShape = 0;
pshpObj = ShapeLib.SHPReadObject(hShp, iShape);
// Get the SHPObject associated with our IntPtr pshpObj
// We create a new SHPObject in managed code, then use Marshal.PtrToStructure
// to copy the unmanaged memory pointed to by pshpObj into our managed copy.
ShapeLib.SHPObject shpObj = new ShapeLib.SHPObject();
Marshal.PtrToStructure(pshpObj, shpObj);
Console.WriteLine("Min XY of shape({0}): ({1}, {2})", iShape, shpObj.dfXMin, shpObj.dfYMin);
Console.WriteLine("Max XY of shape({0}): ({1}, {2})", iShape, shpObj.dfXMax, shpObj.dfYMax);
// Recover the vertices for this shape. Use Marshal.Copy to copy the memory pointed
// to by shpObj.padfX and shpObj.padfX (each an IntPtr) to a actual array.
int iVertex = 2;
Marshal.Copy(shpObj.padfX, xCoord, 0, NVERTICES);
Marshal.Copy(shpObj.padfY, yCoord, 0, NVERTICES);
Console.WriteLine("Vertex XY: ({0}, {1})", xCoord[iVertex], yCoord[iVertex]);
// move some vertices
for (int i=1;i<NVERTICES;i+=2)
{
xCoord[i] = 0.4*Math.Cos(Math.PI/5 * (double)i);
yCoord[i] = -0.4*Math.Sin(Math.PI/5 * (double)i);
}
// scale the figure
for (int i=0;i<NVERTICES;i++)
{
xCoord[i] *= 2;
yCoord[i] *= 2;
}
// Set padfX and padfY to point to our updated array
Marshal.Copy(xCoord, 0, shpObj.padfX, NVERTICES);
Marshal.Copy(yCoord, 0, shpObj.padfY, NVERTICES);
// Copy shpObj to unmanaged memory pointed to by pshpObj
// (shpObj is only a COPY at this point. Use StructureToPtr to
// copy it back for use by shapelib.dll)
Marshal.StructureToPtr(shpObj, pshpObj, true);
// The .NET GC should clean up shpObj, but we'll force the cleanup anyway...
shpObj = null;
// recalculate extents
ShapeLib.SHPComputeExtents(pshpObj);
// write this updated shape to the shapefile, then destroy the SHPObject
iRet = ShapeLib.SHPWriteObject(hShp, iShape, pshpObj);
ShapeLib.SHPDestroyObject(pshpObj);
// verify change was successful
ShapeLib.SHPGetInfo(hShp, ref nEntities, ref shapeType, minB, maxB);
Console.WriteLine("New Min XY: {0}, {1}", minB[0], minB[1]);
Console.WriteLine("New Max XY: {0}, {1}", maxB[0], maxB[1]);
// free resources
ShapeLib.SHPClose(hShp);
Console.WriteLine("\nPress any key to continue...");
Console.ReadLine();
}
private static void CreateDBF()
{
Console.WriteLine("\n*****Creating dbf*****\n");
// create dbase file
IntPtr hDbf = ShapeLib.DBFCreate(FILENAME);
if (hDbf.Equals(IntPtr.Zero))
{
Console.WriteLine("Error: Unable to create {0}.dbf!", FILENAME);
return;
}
// add some fields
int iRet = ShapeLib.DBFAddField(hDbf, "recID", ShapeLib.DBFFieldType.FTInteger, 2, 0);
iRet = ShapeLib.DBFAddField(hDbf, "textField", ShapeLib.DBFFieldType.FTString, 25, 0);
iRet = ShapeLib.DBFAddField(hDbf, "dblField", ShapeLib.DBFFieldType.FTDouble, 8, 4);
iRet = ShapeLib.DBFAddField(hDbf, "boolField", ShapeLib.DBFFieldType.FTLogical, 1,0);
iRet = ShapeLib.DBFAddField(hDbf, "dateField", ShapeLib.DBFFieldType.FTDate, 8,0);
// populate
Random r = new Random();
for (int iShape=0;iShape<NSHAPES;iShape++)
{
int iField = 0;
iRet = (ShapeLib.DBFWriteIntegerAttribute(hDbf, iShape, iField++, iShape * 10));
iRet = (ShapeLib.DBFWriteStringAttribute(hDbf, iShape, iField++, "Hello World"));
iRet = (ShapeLib.DBFWriteDoubleAttribute(hDbf, iShape, iField++, (100 * r.NextDouble())));
iRet = (ShapeLib.DBFWriteLogicalAttribute(hDbf, iShape, iField++, iShape%2==0));
iRet = (ShapeLib.DBFWriteDateAttribute(hDbf, iShape, iField++, DateTime.Now));
}
// set a few null values
iRet = ShapeLib.DBFWriteNULLAttribute(hDbf, 0, 0);
iRet =ShapeLib.DBFWriteNULLAttribute(hDbf, 1, 1);
iRet =ShapeLib.DBFWriteNULLAttribute(hDbf, 2, 2);
iRet =ShapeLib.DBFWriteNULLAttribute(hDbf, 1, 3);
iRet =ShapeLib.DBFWriteNULLAttribute(hDbf, 0, 4);
// modify a value
iRet = (ShapeLib.DBFWriteStringAttribute(hDbf, 2, 1, "Greetings, Earthlings"));
// close the file handle then reopen (only so we can test DBFOpen)
ShapeLib.DBFClose(hDbf);
hDbf = ShapeLib.DBFOpen(FILENAME, "rb+");
// verify the table structure
int recCount =ShapeLib.DBFGetRecordCount(hDbf);
int fieldCount =ShapeLib.DBFGetFieldCount(hDbf);
Console.WriteLine("Record Count: {0}", recCount);
Console.WriteLine("Field Count: {0}\n", fieldCount);
ShapeLib.DBFFieldType[] fieldTypes = new ShapeLib.DBFFieldType[NFIELDS];
string[] fieldNames = new string[NFIELDS];
int fieldWidth=0;
int numDecimals=0;
for (int iField=0;iField<fieldCount;iField++)
{
StringBuilder sb = new StringBuilder(12);
fieldTypes[iField] = ShapeLib.DBFGetFieldInfo(hDbf, iField, sb, ref fieldWidth, ref numDecimals);
fieldNames[iField] = sb.ToString();
Console.WriteLine("-----Field {0}-----", iField+1);
Console.WriteLine("Field Name: {0}", fieldNames[iField]);
Console.WriteLine("Field Type: {0}", fieldTypes[iField]);
Console.WriteLine("Field Width: {0}", fieldWidth);
Console.WriteLine("Num Decimals: {0}", numDecimals);
char c = (char)ShapeLib.DBFGetNativeFieldType(hDbf, iField);
Console.WriteLine("Native Type: {0}", c);
Console.WriteLine("\nPress any key to continue...");
Console.ReadLine();
}
// verify records were written correctly
Console.WriteLine("\n-----Data Values-----");
for (int iShape=0;iShape<recCount;iShape++)
{
for (int iField=0;iField<fieldCount;iField++)
{
switch ((ShapeLib.DBFFieldType)fieldTypes[iField])
{
case (ShapeLib.DBFFieldType.FTDouble):
if (ShapeLib.DBFIsAttributeNULL(hDbf, iShape, iField) == 0)
{
double val = ShapeLib.DBFReadDoubleAttribute(hDbf, iShape, iField);
Console.WriteLine("{0}({1}): {2}", fieldNames[iField], iShape, val);
}
else
Console.WriteLine("{0}({1}) Is Null", fieldNames[iField], iShape);
break;
case (ShapeLib.DBFFieldType.FTLogical):
if (ShapeLib.DBFIsAttributeNULL(hDbf, iShape, iField) == 0)
{
bool val = ShapeLib.DBFReadLogicalAttribute(hDbf, iShape, iField);
Console.WriteLine("{0}({1}): {2}", fieldNames[iField], iShape, val.ToString());
}
else
Console.WriteLine("{0}({1}) Is Null", fieldNames[iField], iShape);
break;
case (ShapeLib.DBFFieldType.FTInteger):
if (ShapeLib.DBFIsAttributeNULL(hDbf, iShape, iField) == 0)
{
int val = ShapeLib.DBFReadIntegerAttribute(hDbf, iShape, iField);
Console.WriteLine("{0}({1}): {2}", fieldNames[iField], iShape, val);
}
else
Console.WriteLine("{0}({1}) Is Null", fieldNames[iField], iShape);
break;
case (ShapeLib.DBFFieldType.FTDate):
if (ShapeLib.DBFIsAttributeNULL(hDbf, iShape, iField) == 0)
{
DateTime val = ShapeLib.DBFReadDateAttribute(hDbf, iShape, iField);
Console.WriteLine("{0}({1}): {2}", fieldNames[iField], iShape, val.ToLongDateString());
}
else
Console.WriteLine("{0}({1}) Is Null", fieldNames[iField], iShape);
break;
case (ShapeLib.DBFFieldType.FTInvalid):
Console.WriteLine("Field type is invalid");
break;
default:
if (ShapeLib.DBFIsAttributeNULL(hDbf, iShape, iField) == 0)
{
string val = ShapeLib.DBFReadStringAttribute(hDbf, iShape, iField);
Console.WriteLine("{0}({1}): {2}", fieldNames[iField], iShape, val);
}
else
Console.WriteLine("{0}({1}) Is Null", fieldNames[iField], iShape);
break;
}
}
}
// check DBFGetFieldIndex function
iRet =ShapeLib.DBFGetFieldIndex(hDbf, "nonexistant");
Console.WriteLine("nonexistant is field #{0}", iRet);
iRet =ShapeLib.DBFGetFieldIndex(hDbf, "dblField");
Console.WriteLine("dblField is field #{0}", iRet);
// check DBFCloneEmpty function
string newFile = FILENAME+"_clone";
IntPtr hDbfClone = ShapeLib.DBFCloneEmpty(hDbf, newFile);
if (hDbfClone.Equals(IntPtr.Zero))
Console.WriteLine("Error: Unable to create {0}.dbf!",newFile);
else
{
// test Tuple Read/Write
int iShape = NSHAPES;
for (int iDest = 0; iDest<NSHAPES; iDest++)
{
IntPtr pTuple = ShapeLib.DBFReadTuple(hDbf, --iShape);
// write to clone in reverse order
// note that iDest must increase monotonically from zero
ShapeLib.DBFWriteTuple(hDbfClone, iDest, pTuple);
Console.WriteLine("Tuple [{0}]->[{1}] = \"{2}\"",
iShape.ToString(),
iDest.ToString(),
Marshal.PtrToStringAnsi(pTuple));
}
// release resources
ShapeLib.DBFClose(hDbfClone);
}
// release resources
ShapeLib.DBFClose(hDbf);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -