//取线段上两点之间的沿线线段
//line 线
//startDist:距离线第一个点的起点位置
//stopDist:距离线第一个点的终点位置
public static List<double[]> lineSliceAlong(List<double[]> line, double startDist, double stopDist)
{
double travelled = 0;
double overshot = 0;
int origCoordsLength = line.Count;
List<double[]> slice = new List<double[]>();
//计算
for (int i = 0; i < line.Count; i++)
{
//如果起始距离大于,起始点位于的线段,且是最后一段儿则停止。
if (startDist >= travelled && i == line.Count - 1) break;
//如果 起始点位于的line分段段小于线段长度,且不是line的第一个点
else if (travelled > startDist && slice.Count == 0)
{
overshot = startDist - travelled;
if (overshot == 0)
{
slice.Add(line[i]);
return slice;
}
//将点沿着向量方向移动距离
Vector3 point1 = new Vector3((float)line[i][0], (float)line[i][1], (float)line[i][2]);
Vector3 point2 = new Vector3((float)line[i - 1][0], (float)line[i - 1][1], (float)line[i - 1][2]);
Vector3 direction = Vector3.Normalize(point1 - point2);
Vector3 moveP = point1 + direction * (float)overshot;
slice.Add(new double[] { moveP.X, moveP.Y, moveP.Z });
slice.Add(new double[] { moveP.X, moveP.Y, moveP.Z });
}
if (travelled >= stopDist)
{
overshot = stopDist - travelled;
if (overshot == 0)
{
slice.Add(line[i]);
return slice;
}
Vector3 point1 = new Vector3((float)line[i][0], (float)line[i][1], (float)line[i][2]);
Vector3 point2 = new Vector3((float)line[i - 1][0], (float)line[i - 1][1], (float)line[i - 1][2]);
Vector3 direction = Vector3.Normalize(point1 - point2);
Vector3 moveP = point1 + direction * (float)overshot;
slice.Add(new double[] { moveP.X, moveP.Y, moveP.Z });
return slice;
}
//线段起点
if (travelled >= startDist)
{
slice.Add(line[i]);
}
if (i == line.Count - 1)
{
return slice;
}
List<double[]> tempLine = new List<double[]> { line[i], line[i + 1] };
travelled += LineLength(tempLine);
}
if (travelled < startDist && line.Count == origCoordsLength)
{
throw new Exception("Start position is beyond line");
}
double[] last = line[line.Count - 1];
var temp = new List<double[]> { last, last };
return temp;
}
//等距分割线
public static List<double[]> lineChunck(List<double[]> line, double segmentLength, bool onlySegementPoint = false)
{
List<double[]> result = new List<double[]>();
double lineLength = LineLength(line);
if (segmentLength <= 0)
{
throw new Exception("segmentLength must be greater than 0");
}
//如果线比分段短,则返回原始数据
if (lineLength <= segmentLength) return line;
double numberOfSegments = lineLength / segmentLength;
//如果分段不是整数则加1
if ((int)numberOfSegments != numberOfSegments)
{
numberOfSegments = Math.Floor(numberOfSegments) + 1;
}
for (int i = 0; i < numberOfSegments; i++)
{
var outLine = lineSliceAlong(line, segmentLength * i, segmentLength * (i + 1));
if (onlySegementPoint)
{
result.Add(outLine.First());
result.Add(outLine.Last());
}
else
{
for (int j = 0; j < outLine.Count; j++)
{
var v = outLine[j];
result.Add(v);
}
}
}
return distinctPoints(result);
}
//点去重
public static List<double[]> distinctPoints(List<double[]> triplets)
{
return triplets
.Distinct(new TripletComparer())
.ToList();
}
private class TripletComparer : IEqualityComparer<double[]>
{
public bool Equals(double[] x, double[] y)
{
if (x.Length != y.Length) return false;
for (int i = 0; i < x.Length; i++)
{
if (x[i] != y[i]) return false;
}
return true;
}
public int GetHashCode(double[] obj)
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
foreach (var val in obj)
{
hash = hash * 23 + val.GetHashCode();
}
return hash;
}
}
}
C# 截取两个点之间的线段,等距分割线
于 2024-08-14 14:04:54 首次发布