【技術分享】【C#】用clipper實現多邊形偏置

freeter
帖子
1
1
精華
0
0
積分
12
12
二次開發
技術分享
Clipper庫是一個開源的C++庫,專門用于線段和多邊形的裁剪以及偏置計算。它提供了一套簡單易用的API,允許開發人員快速地創建復雜的裁剪和偏置算法。參考鏈接:https://www.cnblogs.com/zhigu/p/11943118.html
1.導入clpper庫
2.編寫相關類
由于clipper采用的是整型數據,可以通過適當的縮放數據來計算。同時指出Clipper庫能接受范圍為(4.6+18)的整數坐標值,支持擴展到非常高的精度。這說明我們可以放心得對極小數值進行較大倍數的縮放,不會造成算法的問題,類里采用的精度是1000。
/// <summary>
/// 偏置多邊形(clipper)
/// </summary>
internal class OffsetPolygon
{
/// <summary>
/// clipper中的路徑
/// </summary>
internal List<IntPoint> Path { set; get; }=new List<IntPoint>();
/// <summary>
/// 偏置距離
/// </summary>
internal double OffsetDistance { set; get; }
/// <summary>
/// 精度
/// </summary>
internal double ClipperScale { set; get; } = 1000;
internal OffsetPolygon(List<Point3> point3S, double offsetDistance)
{
for (int i = 0; i < point3S.Count; i++)
{
var x = Math.Round(point3S[i].X, 3) * 1000;
var y = Math.Round(point3S[i].Y, 3) * 1000;
this.Path.Add(new IntPoint(x,y));
}
this.OffsetDistance = offsetDistance;
}
internal List<IntPoint> Commit()
{
int miterLimit = 2;
ClipperOffset co = new ClipperOffset(miterLimit); //向ClipperOffset對象添加一個路徑用來準備偏置
co.AddPath(Path, JoinType.jtRound, EndType.etClosedPolygon);
List<List<IntPoint>> paths=new List<List<IntPoint>>();
co.Execute(ref paths,this.OffsetDistance*1000);
var offsetPath = paths.First();
return offsetPath;
}
3.使用類
var discretePointList = GetSelectFacePointSet(selectFace); //獲取多邊形點集
var cSys = selectFace.AskFaceData().Direction.InitializeZ(selectFace.AskFaceData().Point);
discretePointList =discretePointList.Select(a => a.ToWcs(cSys)).ToList(); //點集轉換(轉換成所在平面的坐標)
OffsetPolygon offsetPolygon=new OffsetPolygon(discretePointList,2); //實例偏置類
var offsetIntPoints = offsetPolygon.Commit();
var offsetPoint3S = offsetIntPoints.Select(a => new Point3((double)a.X / 1000, (double)a.Y / 1000)).ToList();
//相對坐標轉回去
theUfSession.Csys.SetWcs(cSys.Create().Tag);
int inputCSys = UFConstants.UF_CSYS_ROOT_WCS_COORDS;
int outputCSys = UFConstants.UF_CSYS_ROOT_COORDS;
List<Point3> targetPoint3S=new List<Point3>();
for (int i = 0; i < offsetPoint3S.Count; i++)
{
Point3 outputPoint = new Point3();
theUfSession.Csys.MapPoint(inputCSys,offsetPoint3S[i],outputCSys,outputPoint);
targetPoint3S.Add(outputPoint);
}
//臨時線繪制
for (int i = 0; i < targetPoint3S.Count; i++)
{
CreateTempLine(targetPoint3S[i],targetPoint3S[(i+1)%targetPoint3S.Count]);
}
效果圖:
登錄論壇用戶后可查看全部內容
925
0
2023-12-27 17:59:26
請選擇移動至版塊:
確認移動
回復加入討論