2继续NTS库学习(读取shapefile)
引用库如下:
读取shapefile代码如下:
namespace IfoxDemo
{
public class Class1
{
[CommandMethod("xx")]
public static void nts二次学习()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
var ed = doc.Editor;
string shpPath = @"C:\Users\Administrator\Desktop\1.shp";
var shpPath2 = @"C:\Users\Administrator\Desktop\2.shp";
foreach (var feature in NetTopologySuite.IO.Esri.Shapefile.ReadAllFeatures(shpPath2))
{
foreach (var attrName in feature.Attributes.GetNames())
{
ed.WriteMessage($"\n字段名为:\"{attrName,10}\" \n 字段内容为: \"{feature.Attributes[attrName]}\"\n");
}
ed.WriteMessage($" 形状和xy为\"{feature.Geometry}\"\n");
break;
}
ed.WriteMessage("下一个:\n");
foreach (var feature in NetTopologySuite.IO.Esri.Shapefile.ReadAllFeatures(shpPath))
{
foreach (var attrName in feature.Attributes.GetNames())
{
ed.WriteMessage($"字段名为:\"{attrName,10}\" \n 字段内容为: \"{feature.Attributes[attrName]}\n");
}
ed.WriteMessage($" SHAPE: 形状和xy为\"{feature.Geometry}\"\n");
break;
}
}
}
}
读取结果如下:
读取dbf文件如下:
var ed = Env.Editor;
var shpPath = @"C:\Users\Administrator\Desktop\新建文件夹 (2)\zd.shp";
var dbfPath = @"C:\Users\Administrator\Desktop\新建文件夹 (2)\zd.dbf";
using var dbf = new DbfReader(dbfPath);
int id = 0;
foreach (var record in dbf)
{
ed.WriteMessage($"\n第{id}条记录: \n");
foreach (var fieldName in record.GetNames())
{
ed.WriteMessage($"\n字段名为:{fieldName,10} ,字段记录内容为{record[fieldName]}。\n");
}
id++;
}
读取shp文件的几何信息:
var ed = Env.Editor;
var shpPath = @"C:\Users\Administrator\Desktop\新建文件夹 (2)\zd.shp";
var dbfPath = @"C:\Users\Administrator\Desktop\新建文件夹 (2)\zd.dbf";
using var dbf = new DbfReader(dbfPath);
int id = 0;
foreach (NetTopologySuite.Geometries.Geometry geometry in Shapefile.ReadAllGeometries(shpPath))
{
id++;
ed.WriteMessage($"\n第{id}个geometry:"+geometry.ToString());
ed.WriteMessage("\ngeometry的类型为:"+geometry.GetType().ToString()+"\n");
// 根据几何类型提取坐标点
List<Point3d> points = new List<Point3d>();
if (geometry is Point point)
{
// 如果是点类型
points.Add(new Point3d(point.X, point.Y, point.Z)); // 假设 Z 坐标为 0
}
else if (geometry is LineString lineString)
{
// 如果是线类型
foreach (Coordinate coord in lineString.Coordinates)
{
points.Add(new Point3d(coord.X, coord.Y, coord.Z)); // 假设 Z 坐标为 0
}
}
else if (geometry is Polygon polygon)
{
// 如果是面类型
foreach (Coordinate coord in polygon.ExteriorRing.Coordinates)
{
points.Add(new Point3d(coord.X, coord.Y, coord.Z)); // 假设 Z 坐标为 0
}
}
// 其他几何类型(如 MultiPoint、MultiLineString、MultiPolygon 等)可以类似处理
else if (geometry is MultiPolygon multiPolygon)
{
// 遍历 MultiPolygon 中的每个 Polygon
foreach (Polygon polygon1 in multiPolygon.Geometries)
{
// 提取外环的坐标点
foreach (Coordinate coord in polygon1.ExteriorRing.Coordinates)
{
points.Add(new Point3d(coord.X, coord.Y, coord.Z)); // 假设 Z 坐标为 0
}
// 提取内环的坐标点
foreach (LineString interiorRing in polygon1.InteriorRings)
{
foreach (Coordinate coord in interiorRing.Coordinates)
{
points.Add(new Point3d(coord.X, coord.Y, coord.Z)); // 假设 Z 坐标为 0
}
}
}
}
int j = 0;
foreach(var pt in points)
{
j++;
ed.WriteMessage($"\n第{j}个坐标\n");
ed.WriteMessage($"x:{pt.X},y:{pt.X}\n");
}
}
写入shapefile
using GeoAPI.Geometries;
using NetTopologySuite.Features;
using NetTopologySuite.Geometries;
using NetTopologySuite;
using NetTopologySuite.IO;
using Coordinate = NetTopologySuite.Geometries.Coordinate;
using GeoAPI;
using NetTopologySuite.Operation.Polygonize;
using System.Threading;
using Point = NetTopologySuite.Geometries.Point;
using Polygon = NetTopologySuite.Geometries.Polygon;
using IFoxCAD.Cad;
using NetTopologySuite.Index.Quadtree;
using NetTopologySuite.Index.Strtree;
using NetTopologySuite.Triangulate;
using NetTopologySuite.Operation.Linemerge;
using NetTopologySuite.IO.Esri;
using NetTopologySuite.IO.Esri.Shapefiles.Readers;
using NetTopologySuite.IO.Esri.Dbf;
using NetTopologySuite.IO.Esri.Shp.Readers;
using NetTopologySuite.Algorithm;
[assembly: CommandClass(typeof(IfoxDemo.NTS自己))]//只允许此类快捷键命令
namespace IfoxDemo
{
public class NTS自己
{
[CommandMethod("xx")]
public static void shp()
{
var shpPath = @"C:\Users\Administrator\Desktop\新建文件夹 (2)\zd5.shp";
var features = new List<Feature>();
for (int i = 1; i < 500; i++)
{
var lineCoords = new List<CoordinateZ>
{
new CoordinateZ(i, i + 1, i),
new CoordinateZ(i, i, i),
new CoordinateZ(i + 1, i, i)
};
var line = new LineString(lineCoords.ToArray());
var mline = new MultiLineString(new LineString[] { line });
var attributes = new AttributesTable
{
{ "date", new DateTime(2000, 1, 1) },
{ "float", i * 0.1 },
{ "int", i },
{ "logical", i % 2 == 0 },
{ "text", i.ToString("0.00") }
};
var feature = new Feature(mline, attributes);
features.Add(feature);
}
Shapefile.WriteAllFeatures(features, shpPath);
}
}
}
double.NaN
是 C# 中表示 非数字(Not a Number) 的特殊值。它是 double
类型的一个常量,用于表示无效或未定义的数值结果。以下是关于 double.NaN
的详细说明:
1. 什么是 double.NaN
?
-
定义:
NaN
是 IEEE 754 浮点数标准中定义的一个特殊值,表示 非数字。 -
特点:
-
它不是任何具体的数值。
-
它用于表示无效的数学运算结果(如
0 / 0
或Math.Sqrt(-1)
)。 -
它与任何值(包括它自己)的比较结果都是
false
。
-
# NetTopologySuite.IO.Esri
This library provides forward-only readers and writers for [Esri shapefiles](https://support.esri.com/en/white-paper/279).
## DBF
Shapefile feature attributes are held in a [dBASE format file](dBASE.md) (.dbf extension). Each attribute record
has a one-to-one relationship with the associated shape record. Classes whose name starts
with `Dbf` (eg. `DbfReader`) provide direct access to dBASE files.
```c#
using var dbf = new DbfReader(dbfPath);
foreach (var record in dbf)
{
foreach (var fieldName in record.GetNames())
{
Console.WriteLine($"{fieldName,10} {record[fieldName]}");
}
Console.WriteLine();
}
```
## SHP
The main file (.shp extension) is a variable-record-length file in which each record describes
a shape with a list of its vertices. Classes whose name starts with `Shp` (eg. `ShpPointReader`)
provide direct access to main file.
```c#
foreach (var geometry in Shapefile.ReadAllGeometries(shpPath))
{
Console.WriteLine(geometry);
}
```
## SHX
The index file (.shx extension) stores the offset and content length for each record in SHP file.
As there is no additional value, this file is ignored during reading shapefiles.
Writing SHX data is handled directly by `ShpWriter` classes.
## Shapefile
All three files described above form a shapefile. Unified access to shapefile triplet
is provided through classes whose name starts with `Shapefile` (eg. `ShapefilePointReader`).
Under the hood they are decorators wrapping `Dbf` and `Shp` classes.
### Reading shapefiles using c# code
```c#
foreach (var feature in Shapefile.ReadAllFeatures(shpPath))
{
foreach (var attrName in feature.Attributes.GetNames())
{
Console.WriteLine($"{attrName,10}: {feature.Attributes[attrName]}");
}
Console.WriteLine($" SHAPE: {feature.Geometry}");
Console.WriteLine();
}
```
### Writing shapefiles using c# code
The most common variant of writing shapefiles is to use `Shapefile.WriteAllFeatures` method.
```c#
var features = new List<Feature>();
for (int i = 1; i < 5; i++)
{
var lineCoords = new List<CoordinateZ>
{
new CoordinateZ(i, i + 1, i),
new CoordinateZ(i, i, i),
new CoordinateZ(i + 1, i, i)
};
var line = new LineString(lineCoords.ToArray());
var mline = new MultiLineString(new LineString[] { line });
var attributes = new AttributesTable
{
{ "date", new DateTime(2000, 1, i + 1) },
{ "float", i * 0.1 },
{ "int", i },
{ "logical", i % 2 == 0 },
{ "text", i.ToString("0.00") }
};
var feature = new Feature(mline, attributes);
features.Add(feature);
}
Shapefile.WriteAllFeatures(features, shpPath);
```
The most efficient way to write large shapefiles is to use `ShapefileWriter` class.
This variant should also be used when you need to write a shapefile with a attributes containing `null` values.
```c#
var fields = new List<DbfField>();
var dateField = fields.AddDateField("date");
var floatField = fields.AddFloatField("float");
var intField = fields.AddNumericInt32Field("int");
var logicalField = fields.AddLogicalField("logical");
var textField = fields.AddCharacterField("text");
var options = new ShapefileWriterOptions(ShapeType.PolyLine, fields.ToArray());
using (var shpWriter = Shapefile.OpenWrite(shpPath, options))
{
for (var i = 1; i < 5; i++)
{
var lineCoords = new List<Coordinate>
{
new(i, i + 1),
new(i, i),
new(i + 1, i)
};
var line = new LineString(lineCoords.ToArray());
var mline = new MultiLineString(new LineString[] { line });
int? nullIntValue = null;
shpWriter.Geometry = mline;
dateField.DateValue = DateTime.Now;
floatField.NumericValue = i * 0.1;
intField.NumericValue = nullIntValue;
logicalField.LogicalValue = i % 2 == 0;
textField.StringValue = i.ToString("0.00");
shpWriter.Write();
}
}
```
## Encoding
The .NET Framework supports a large number of character encodings and code pages.
On the other hand, .NET Core only supports
[limited list](https://docs.microsoft.com/en-us/dotnet/api/system.text.codepagesencodingprovider.instance#remarks) of encodings.
To retrieve an encoding that is present in the .NET Framework on the Windows
desktop but not in .NET Core, you need to do the following:
1. Add to your project reference to to the [System.Text.Encoding.CodePages.dll](https://www.nuget.org/packages/System.Text.Encoding.CodePages/).
2. Put the following line somewhere in your code:
`Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);`
## Install using NuGet package manager
Stable releases are hosted on the default NuGet feed. You can install them using the following command on the package manager command line
```console
PM> NuGet\Install-Package NetTopologySuite.IO.Esri.Shapefile
```