05-几何运算操作符
第五章:几何运算操作符
5.1 概述
几何运算操作符用于对几何对象进行变换和计算,生成新的几何对象或计算几何属性。这些操作符是空间分析的核心工具。
5.1.1 操作符分类
| 类别 | 操作符 | 说明 |
|---|---|---|
| 创建型 | BufferOperator | 创建缓冲区 |
| 创建型 | ConvexHullOperator | 计算凸包 |
| 创建型 | BoundaryOperator | 获取边界 |
| 创建型 | OffsetOperator | 创建偏移几何 |
| 计算型 | AreaOperator | 计算面积 |
| 计算型 | LengthOperator | 计算长度 |
| 计算型 | CentroidOperator | 计算质心 |
| 变换型 | SimplifyOperator | 简化几何 |
| 变换型 | GeneralizeOperator | 概化几何 |
| 变换型 | DensifyOperator | 密化几何 |
| 变换型 | ClipOperator | 裁剪几何 |
5.2 Buffer(缓冲区)
5.2.1 概念
缓冲区操作在几何对象周围创建指定距离的区域。这是 GIS 分析中最常用的操作之一。
应用场景:
- 创建服务区域(如配送范围)
- 环境影响分析(如噪音影响范围)
- 安全距离分析(如河流泛滥区)
5.2.2 API
public class BufferOperator : IGeometryOperator<Polygon>
{
public static BufferOperator Instance { get; }
public Polygon Execute(Geometry geometry, double distance,
SpatialReference? spatialRef = null);
}
5.2.3 使用示例
using Esri.Geometry.Core;
using Esri.Geometry.Core.Geometries;
// 点缓冲区
var point = new Point(100, 100);
var buffer = GeometryEngine.Buffer(point, 10);
Console.WriteLine($"缓冲区类型:{buffer.Type}"); // Polygon
Console.WriteLine($"环数:{buffer.RingCount}"); // 1
// 包络矩形缓冲区
var envelope = new Envelope(0, 0, 50, 30);
var envBuffer = GeometryEngine.Buffer(envelope, 5);
// 缓冲区扩展了各方向 5 个单位
var bufferEnv = envBuffer.GetEnvelope();
Console.WriteLine($"缓冲区范围:({bufferEnv.XMin}, {bufferEnv.YMin}) - ({bufferEnv.XMax}, {bufferEnv.YMax})");
// 输出:(-5, -5) - (55, 35)
5.2.4 实现原理
当前实现为简化版本,创建矩形缓冲区:
private Polygon BufferPoint(Point point, double distance)
{
// 在点周围创建正方形缓冲区
var polygon = new Polygon();
var ring = new List<Point>
{
new Point(point.X - distance, point.Y - distance),
new Point(point.X + distance, point.Y - distance),
new Point(point.X + distance, point.Y + distance),
new Point(point.X - distance, point.Y + distance),
new Point(point.X - distance, point.Y - distance) // 闭合
};
polygon.AddRing(ring);
return polygon;
}
private Polygon BufferEnvelope(Envelope envelope, double distance)
{
// 在各个方向上扩展包络
var polygon = new Polygon();
var ring = new List<Point>
{
new Point(envelope.XMin - distance, envelope.YMin - distance),
new Point(envelope.XMax + distance, envelope.YMin - distance),
new Point(envelope.XMax + distance, envelope.YMax + distance),
new Point(envelope.XMin - distance, envelope.YMax + distance),
new Point(envelope.XMin - distance, envelope.YMin - distance)
};
polygon.AddRing(ring);
return polygon;
}
5.2.5 应用示例
// 场景:创建商店的配送范围
var storeLocation = new Point(116.4074, 39.9042);
var deliveryRadius = 0.02; // 约 2 公里(经纬度)
var deliveryZone = GeometryEngine.Buffer(storeLocation, deliveryRadius);
// 检查客户是否在配送范围内
var customerLocation = new Point(116.41, 39.91);
bool canDeliver = GeometryEngine.Contains(deliveryZone, customerLocation);
Console.WriteLine($"可以配送:{canDeliver}");
5.3 ConvexHull(凸包)
5.3.1 概念
凸包是包含给定点集的最小凸多边形。可以想象为用橡皮筋套住一组钉子形成的形状。
应用场景:
- 计算点集的最小外接多边形
- 碰撞检测的预处理
- 地理范围估计
5.3.2 API
public class ConvexHullOperator : IGeometryOperator<Geometry>
{
public static ConvexHullOperator Instance { get; }
public Geometry Execute(Geometry geometry,
SpatialReference? spatialRef = null);
}
5.3.3 使用示例
using Esri.Geometry.Core;
using Esri.Geometry.Core.Geometries;
// 多点的凸包
var multiPoint = new MultiPoint();
multiPoint.Add(new Point(0, 0));
multiPoint.Add(new Point(10, 0));
multiPoint.Add(new Point(5, 5));
multiPoint.Add(new Point(10, 10));
multiPoint.Add(new Point(0, 10));
multiPoint.Add(new Point(5, 3)); // 内部点
var hull = GeometryEngine.ConvexHull(multiPoint);
if (hull is Polygon polygon)
{
Console.WriteLine($"凸包顶点数:{polygon.GetRing(0).Count}");
// 内部点 (5, 3) 不在凸包边界上
}
// 折线的凸包
var polyline = new Polyline();
polyline.AddPath(new List<Point>
{
new Point(0, 0),
new Point(5, 10),
new Point(10, 0)
});
var lineHull = GeometryEngine.ConvexHull(polyline); // 返回三角形
5.3.4 实现原理:Graham 扫描算法
private List<Point> GrahamScan(List<Point> points)
{
if (points.Count < 3) return points;
// 1. 找到 Y 坐标最小的点(最低点)
var lowestPoint = points.OrderBy(p => p.Y).ThenBy(p => p.X).First();
// 2. 按极角排序其他点
var sortedPoints = points
.Where(p => p != lowestPoint)
.OrderBy(p => Math.Atan2(p.Y - lowestPoint.Y, p.X - lowestPoint.X))
.ThenBy(p => p.Distance(lowestPoint))
.ToList();
// 3. 构建凸包
var hull = new List<Point> { lowestPoint };
foreach (var point in sortedPoints)
{
// 移除产生右转的点
while (hull.Count > 1 && !IsLeftTurn(hull[hull.Count - 2], hull[hull.Count - 1], point))
{
hull.RemoveAt(hull.Count - 1);
}
hull.Add(point);
}
return hull;
}
private bool IsLeftTurn(Point p1, Point p2, Point p3)
{
// 使用叉积判断是否左转
var cross = (p2.X - p1.X) * (p3.Y - p1.Y) - (p2.Y - p1.Y) * (p3.X - p1.X);
return cross > 0;
}
算法复杂度:O(n log n),其中 n 是点的数量。
5.3.5 返回类型
根据输入几何的不同,凸包返回不同类型:
| 输入点数 | 返回类型 |
|---|---|
| 0 | 空 Polygon |
| 1 | Point |
| 2 | Line |
| ≥3 | Polygon |
5.4 Area 和 Length(面积和长度)
5.4.1 概念
- Area(面积):计算多边形或包络矩形的二维面积
- Length(长度):计算折线的总长度或多边形的周长
5.4.2 API
public class AreaOperator : IGeometryOperator<double>
{
public static AreaOperator Instance { get; }
public double Execute(Geometry geometry,
SpatialReference? spatialRef = null);
}
public class LengthOperator : IGeometryOperator<double>
{
public static LengthOperator Instance { get; }
public double Execute(Geometry geometry,
SpatialReference? spatialRef = null);
}
5.4.3 使用示例
using Esri.Geometry.Core;
using Esri.Geometry.Core.Geometries;
// 计算多边形面积
var polygon = new Polygon();
polygon.AddRing(new List<Point>
{
new Point(0, 0),
new Point(10, 0),
new Point(10, 10),
new Point(0, 10),
new Point(0, 0)
});
double area = GeometryEngine.Area(polygon);
Console.WriteLine($"多边形面积:{area}"); // 100
// 计算包络矩形面积
var envelope = new Envelope(0, 0, 100, 50);
double envArea = GeometryEngine.Area(envelope);
Console.WriteLine($"包络面积:{envArea}"); // 5000
// 计算折线长度
var polyline = new Polyline();
polyline.AddPath(new List<Point>
{
new Point(0, 0),
new Point(3, 4), // 距离原点 5
new Point(3, 14) // 向上 10
});
double length = GeometryEngine.Length(polyline);
Console.WriteLine($"折线长度:{length}"); // 15
// 计算多边形周长
double perimeter = GeometryEngine.Length(polygon);
Console.WriteLine($"多边形周长:{perimeter}"); // 40
5.4.4 面积计算:鞋带公式
public double Execute(Geometry geometry, SpatialReference? spatialRef = null)
{
if (geometry is Polygon polygon)
{
double area = 0;
foreach (var ring in polygon.GetRings())
{
var count = ring.Count;
if (count < 3) continue;
double ringArea = 0;
for (var i = 0; i < count - 1; i++)
{
// 鞋带公式
ringArea += ring[i].X * ring[i + 1].Y - ring[i + 1].X * ring[i].Y;
}
// 闭合环
ringArea += ring[count - 1].X * ring[0].Y - ring[0].X * ring[count - 1].Y;
area += Math.Abs(ringArea) * 0.5;
}
return area;
}
if (geometry is Envelope envelope)
{
return envelope.Width * envelope.Height;
}
return 0; // 点和线没有面积
}
5.4.5 长度计算
public double Execute(Geometry geometry, SpatialReference? spatialRef = null)
{
if (geometry is Polyline polyline)
{
double length = 0;
foreach (var path in polyline.GetPaths())
{
for (var i = 0; i < path.Count - 1; i++)
{
length += path[i].Distance(path[i + 1]);
}
}
return length;
}
if (geometry is Polygon polygon)
{
double length = 0;
foreach (var ring in polygon.GetRings())
{
for (var i = 0; i < ring.Count - 1; i++)
{
length += ring[i].Distance(ring[i + 1]);
}
// 闭合段
if (ring.Count > 1)
{
length += ring[ring.Count - 1].Distance(ring[0]);
}
}
return length;
}
return 0; // 点没有长度
}
5.5 Simplify(简化)
5.5.1 概念
使用 Douglas-Peucker 算法减少几何对象的顶点数量,同时保持其基本形状。常用于减少数据量,提高渲染性能。
应用场景:
- 地图缩放时简化显示
- 减少存储和传输的数据量
- 提高地图渲染速度
5.5.2 API
public class SimplifyOperator : IGeometryOperator<Geometry>
{
public static SimplifyOperator Instance { get; }
public Geometry Execute(Geometry geometry, double tolerance,
SpatialReference? spatialRef = null);
}
5.5.3 使用示例
using Esri.Geometry.Core;
using Esri.Geometry.Core.Geometries;
// 创建包含多个点的折线
var polyline = new Polyline();
polyline.AddPath(new List<Point>
{
new Point(0, 0),
new Point(1, 0.1), // 几乎在直线上
new Point(2, 0.05), // 几乎在直线上
new Point(3, 0.08), // 几乎在直线上
new Point(4, 0),
new Point(5, 5), // 明显转折
new Point(6, 4.9), // 几乎在直线上
new Point(7, 5.1), // 几乎在直线上
new Point(8, 5),
new Point(9, 0),
new Point(10, 0)
});
Console.WriteLine($"原始点数:{polyline.GetPath(0).Count}"); // 11
// 使用容差 0.2 简化
var simplified = GeometryEngine.Simplify(polyline, 0.2);
if (simplified is Polyline simplifiedLine)
{
Console.WriteLine($"简化后点数:{simplifiedLine.GetPath(0).Count}"); // 减少
}
// 使用更大的容差会更激进地简化
var moreSimplified = GeometryEngine.Simplify(polyline, 1.0);
5.5.4 实现原理:Douglas-Peucker 算法
private List<Point> DouglasPeucker(List<Point> points, double tolerance)
{
if (points.Count < 3) return points;
// 1. 找到距离首尾连线最远的点
double maxDistance = 0;
int maxIndex = 0;
int end = points.Count - 1;
for (int i = 1; i < end; i++)
{
double distance = PerpendicularDistance(points[i], points[0], points[end]);
if (distance > maxDistance)
{
maxDistance = distance;
maxIndex = i;
}
}
// 2. 如果最大距离超过容差,递归处理两段
if (maxDistance > tolerance)
{
var left = DouglasPeucker(points.GetRange(0, maxIndex + 1), tolerance);
var right = DouglasPeucker(points.GetRange(maxIndex, end - maxIndex + 1), tolerance);
// 合并结果(去掉重复的中间点)
var result = new List<Point>(left);
result.AddRange(right.Skip(1));
return result;
}
// 3. 否则只保留端点
return new List<Point> { points[0], points[end] };
}
// 计算点到线段的垂直距离
private double PerpendicularDistance(Point point, Point lineStart, Point lineEnd)
{
double dx = lineEnd.X - lineStart.X;
double dy = lineEnd.Y - lineStart.Y;
double mag = Math.Sqrt(dx * dx + dy * dy);
if (mag < GeometryConstants.Epsilon)
return point.Distance(lineStart);
// 参数化位置
double u = ((point.X - lineStart.X) * dx + (point.Y - lineStart.Y) * dy) / (mag * mag);
if (u < 0) return point.Distance(lineStart);
if (u > 1) return point.Distance(lineEnd);
// 最近点
double ix = lineStart.X + u * dx;
double iy = lineStart.Y + u * dy;
return point.Distance(new Point(ix, iy));
}
算法复杂度:平均 O(n log n),最坏 O(n²)。
5.6 Centroid(质心)
5.6.1 概念
质心是几何对象的几何中心点(质量中心)。
5.6.2 API
public class CentroidOperator : IGeometryOperator<Point>
{
public static CentroidOperator Instance { get; }
public Point Execute(Geometry geometry,
SpatialReference? spatialRef = null);
}
5.6.3 使用示例
using Esri.Geometry.Core;
using Esri.Geometry.Core.Geometries;
// 多边形的质心
var polygon = new Polygon();
polygon.AddRing(new List<Point>
{
new Point(0, 0),
new Point(10, 0),
new Point(10, 10),
new Point(0, 10),
new Point(0, 0)
});
var centroid = GeometryEngine.Centroid(polygon);
Console.WriteLine($"质心:({centroid.X}, {centroid.Y})"); // (5, 5)
// 多点的质心(平均值)
var multiPoint = new MultiPoint();
multiPoint.Add(new Point(0, 0));
multiPoint.Add(new Point(10, 0));
multiPoint.Add(new Point(10, 10));
multiPoint.Add(new Point(0, 10));
var mpCentroid = GeometryEngine.Centroid(multiPoint);
Console.WriteLine($"多点质心:({mpCentroid.X}, {mpCentroid.Y})"); // (5, 5)
// 三角形的质心
var triangle = new Polygon();
triangle.AddRing(new List<Point>
{
new Point(0, 0),
new Point(6, 0),
new Point(3, 6),
new Point(0, 0)
});
var triangleCentroid = GeometryEngine.Centroid(triangle);
Console.WriteLine($"三角形质心:({triangleCentroid.X}, {triangleCentroid.Y})"); // (3, 2)
5.6.4 实现原理
public Point Execute(Geometry geometry, SpatialReference? spatialRef = null)
{
if (geometry.IsEmpty)
return new Point();
switch (geometry.Type)
{
case GeometryType.Point:
return (Point)geometry;
case GeometryType.MultiPoint:
return CalculateMultiPointCentroid((MultiPoint)geometry);
case GeometryType.Polygon:
return CalculatePolygonCentroid((Polygon)geometry);
case GeometryType.Envelope:
return ((Envelope)geometry).Center;
default:
// 对于其他类型,返回包络的中心
return geometry.GetEnvelope().Center;
}
}
private Point CalculateMultiPointCentroid(MultiPoint multiPoint)
{
double sumX = 0, sumY = 0;
int count = 0;
foreach (var point in multiPoint.GetPoints())
{
sumX += point.X;
sumY += point.Y;
count++;
}
return new Point(sumX / count, sumY / count);
}
private Point CalculatePolygonCentroid(Polygon polygon)
{
// 使用多边形质心公式
double sumX = 0, sumY = 0, sumArea = 0;
foreach (var ring in polygon.GetRings())
{
for (int i = 0; i < ring.Count - 1; i++)
{
double cross = ring[i].X * ring[i + 1].Y - ring[i + 1].X * ring[i].Y;
sumX += (ring[i].X + ring[i + 1].X) * cross;
sumY += (ring[i].Y + ring[i + 1].Y) * cross;
sumArea += cross;
}
}
double area = sumArea / 2;
return new Point(sumX / (6 * area), sumY / (6 * area));
}
5.7 Boundary(边界)
5.7.1 概念
边界操作返回几何对象的边界几何。根据 OGC 规范:
- 点的边界是空
- 线的边界是端点
- 多边形的边界是其环
5.7.2 API
public class BoundaryOperator : IGeometryOperator<Geometry>
{
public static BoundaryOperator Instance { get; }
public Geometry Execute(Geometry geometry,
SpatialReference? spatialRef = null);
}
5.7.3 使用示例
using Esri.Geometry.Core;
using Esri.Geometry.Core.Geometries;
// 点的边界是空
var point = new Point(10, 20);
var pointBoundary = GeometryEngine.Boundary(point);
Console.WriteLine($"点边界为空:{pointBoundary.IsEmpty}"); // true
// 折线的边界是端点
var polyline = new Polyline();
polyline.AddPath(new List<Point>
{
new Point(0, 0),
new Point(10, 10),
new Point(20, 0)
});
var lineBoundary = GeometryEngine.Boundary(polyline);
if (lineBoundary is MultiPoint boundaryPoints)
{
Console.WriteLine($"折线边界点数:{boundaryPoints.Count}"); // 2(起点和终点)
}
// 多边形的边界是折线
var polygon = new Polygon();
polygon.AddRing(new List<Point>
{
new Point(0, 0),
new Point(10, 0),
new Point(10, 10),
new Point(0, 10),
new Point(0, 0)
});
var polyBoundary = GeometryEngine.Boundary(polygon);
if (polyBoundary is Polyline boundaryLine)
{
Console.WriteLine($"多边形边界长度:{boundaryLine.Length}"); // 40
}
5.8 Generalize(概化)
5.8.1 概念
概化操作通过删除顶点来简化几何对象,同时保持其总体形状。与 Simplify 类似,但参数含义不同:
- Simplify:tolerance 是点到简化线的最大距离
- Generalize:maxDeviation 是允许的最大偏差
5.8.2 API
public class GeneralizeOperator : IGeometryOperator<Geometry>
{
public static GeneralizeOperator Instance { get; }
public Geometry Execute(Geometry geometry, double maxDeviation,
SpatialReference? spatialRef = null);
}
5.8.3 使用示例
using Esri.Geometry.Core;
using Esri.Geometry.Core.Geometries;
var polyline = new Polyline();
polyline.AddPath(new List<Point>
{
new Point(0, 0),
new Point(1, 0.5),
new Point(2, 0),
new Point(3, 0.3),
new Point(4, 0),
new Point(5, 1),
new Point(6, 0)
});
Console.WriteLine($"原始点数:{polyline.GetPath(0).Count}"); // 7
var generalized = GeometryEngine.Generalize(polyline, 0.6);
if (generalized is Polyline genLine)
{
Console.WriteLine($"概化后点数:{genLine.GetPath(0).Count}"); // 减少
}
5.9 Densify(密化)
5.9.1 概念
密化操作在几何对象的线段上添加额外的顶点,确保没有线段超过指定的最大长度。这是概化的逆操作。
应用场景:
- 为投影转换准备几何
- 沿曲线均匀采样
- 提高空间分析精度
5.9.2 API
public class DensifyOperator : IGeometryOperator<Geometry>
{
public static DensifyOperator Instance { get; }
public Geometry Execute(Geometry geometry, double maxSegmentLength,
SpatialReference? spatialRef = null);
}
5.9.3 使用示例
using Esri.Geometry.Core;
using Esri.Geometry.Core.Geometries;
// 简单的两点折线
var polyline = new Polyline();
polyline.AddPath(new List<Point>
{
new Point(0, 0),
new Point(10, 0) // 长度为 10 的线段
});
Console.WriteLine($"原始点数:{polyline.GetPath(0).Count}"); // 2
// 密化,最大线段长度为 2
var densified = GeometryEngine.Densify(polyline, 2);
if (densified is Polyline denLine)
{
Console.WriteLine($"密化后点数:{denLine.GetPath(0).Count}"); // 6
// 点:(0,0), (2,0), (4,0), (6,0), (8,0), (10,0)
}
// 多边形密化
var square = new Polygon();
square.AddRing(new List<Point>
{
new Point(0, 0),
new Point(10, 0),
new Point(10, 10),
new Point(0, 10),
new Point(0, 0)
});
var densifiedSquare = GeometryEngine.Densify(square, 3);
5.9.4 实现原理
private List<Point> DensifyPath(IReadOnlyList<Point> path, double maxLength)
{
var result = new List<Point>();
for (int i = 0; i < path.Count - 1; i++)
{
result.Add(path[i]);
var start = path[i];
var end = path[i + 1];
double length = start.Distance(end);
if (length > maxLength)
{
// 计算需要插入的点数
int numSegments = (int)Math.Ceiling(length / maxLength);
for (int j = 1; j < numSegments; j++)
{
double t = (double)j / numSegments;
result.Add(new Point(
start.X + t * (end.X - start.X),
start.Y + t * (end.Y - start.Y)
));
}
}
}
result.Add(path[path.Count - 1]);
return result;
}
5.10 Clip(裁剪)
5.10.1 概念
裁剪操作将几何对象裁剪到指定的包络矩形范围内。常用于视口裁剪和数据范围限制。
5.10.2 API
public class ClipOperator : IGeometryOperator<Geometry>
{
public static ClipOperator Instance { get; }
public Geometry Execute(Geometry geometry, Envelope clipEnvelope);
}
5.10.3 使用示例
using Esri.Geometry.Core;
using Esri.Geometry.Core.Geometries;
// 创建裁剪范围
var clipEnvelope = new Envelope(0, 0, 50, 50);
// 裁剪点
var pointInside = new Point(25, 25);
var pointOutside = new Point(100, 100);
var clippedIn = GeometryEngine.Clip(pointInside, clipEnvelope); // 返回原点
var clippedOut = GeometryEngine.Clip(pointOutside, clipEnvelope); // 返回空点
// 裁剪折线(Cohen-Sutherland 算法)
var polyline = new Polyline();
polyline.AddPath(new List<Point>
{
new Point(-10, 25), // 裁剪区外
new Point(25, 25), // 裁剪区内
new Point(75, 25) // 裁剪区外
});
var clippedLine = GeometryEngine.Clip(polyline, clipEnvelope);
// 结果:从 (0, 25) 到 (50, 25) 的线段
5.10.4 实现原理:Cohen-Sutherland 算法
// 区域码定义
private const int INSIDE = 0; // 0000
private const int LEFT = 1; // 0001
private const int RIGHT = 2; // 0010
private const int BOTTOM = 4; // 0100
private const int TOP = 8; // 1000
private int ComputeOutCode(double x, double y, Envelope clip)
{
int code = INSIDE;
if (x < clip.XMin) code |= LEFT;
else if (x > clip.XMax) code |= RIGHT;
if (y < clip.YMin) code |= BOTTOM;
else if (y > clip.YMax) code |= TOP;
return code;
}
private Line? ClipLine(Point p1, Point p2, Envelope clip)
{
int outcode1 = ComputeOutCode(p1.X, p1.Y, clip);
int outcode2 = ComputeOutCode(p2.X, p2.Y, clip);
double x1 = p1.X, y1 = p1.Y;
double x2 = p2.X, y2 = p2.Y;
while (true)
{
if ((outcode1 | outcode2) == 0)
{
// 两点都在内部
return new Line(new Point(x1, y1), new Point(x2, y2));
}
else if ((outcode1 & outcode2) != 0)
{
// 线段完全在外部
return null;
}
else
{
// 需要裁剪
int outcodeOut = outcode1 != 0 ? outcode1 : outcode2;
double x, y;
if ((outcodeOut & TOP) != 0)
{
x = x1 + (x2 - x1) * (clip.YMax - y1) / (y2 - y1);
y = clip.YMax;
}
else if ((outcodeOut & BOTTOM) != 0)
{
x = x1 + (x2 - x1) * (clip.YMin - y1) / (y2 - y1);
y = clip.YMin;
}
else if ((outcodeOut & RIGHT) != 0)
{
y = y1 + (y2 - y1) * (clip.XMax - x1) / (x2 - x1);
x = clip.XMax;
}
else
{
y = y1 + (y2 - y1) * (clip.XMin - x1) / (x2 - x1);
x = clip.XMin;
}
// 更新端点
if (outcodeOut == outcode1)
{
x1 = x; y1 = y;
outcode1 = ComputeOutCode(x1, y1, clip);
}
else
{
x2 = x; y2 = y;
outcode2 = ComputeOutCode(x2, y2, clip);
}
}
}
}
5.11 Offset(偏移)
5.11.1 概念
偏移操作创建几何对象的偏移版本。正值向外偏移,负值向内偏移。
5.11.2 API
public class OffsetOperator : IGeometryOperator<Geometry>
{
public static OffsetOperator Instance { get; }
public Geometry Execute(Geometry geometry, double distance,
SpatialReference? spatialRef = null);
}
5.11.3 使用示例
using Esri.Geometry.Core;
using Esri.Geometry.Core.Geometries;
// 多边形偏移
var polygon = new Polygon();
polygon.AddRing(new List<Point>
{
new Point(0, 0),
new Point(100, 0),
new Point(100, 100),
new Point(0, 100),
new Point(0, 0)
});
// 向外偏移 10
var offsetPolygon = GeometryEngine.Offset(polygon, 10);
// 向内偏移 10
var insetPolygon = GeometryEngine.Offset(polygon, -10);
5.12 小结
本章详细介绍了 geometry-api-net 的几何运算操作符:
| 操作符 | 功能 | 核心算法 |
|---|---|---|
| Buffer | 创建缓冲区 | 几何扩展 |
| ConvexHull | 计算凸包 | Graham 扫描 |
| Area | 计算面积 | 鞋带公式 |
| Length | 计算长度 | 欧几里得距离 |
| Simplify | 简化几何 | Douglas-Peucker |
| Centroid | 计算质心 | 多边形质心公式 |
| Boundary | 获取边界 | OGC 规范 |
| Generalize | 概化几何 | Douglas-Peucker 变体 |
| Densify | 密化几何 | 线段插值 |
| Clip | 裁剪几何 | Cohen-Sutherland |
| Offset | 偏移几何 | 几何偏移 |
这些操作符是进行空间分析的核心工具。在下一章中,我们将学习集合操作符,用于计算几何对象之间的并集、交集和差集。

浙公网安备 33010602011771号