public IPolylineD3D ShortenedBy(RADouble marginAtStart, RADouble marginAtEnd) { if (_points.Length < 2) { return(null); } double totLength = TotalLineLength; double a1 = marginAtStart.IsAbsolute ? marginAtStart.Value : marginAtStart.Value * totLength; double a2 = marginAtEnd.IsAbsolute ? marginAtEnd.Value : marginAtEnd.Value * totLength; if (!((a1 + a2) < totLength)) { return(null); } PointD3D?p0 = null; PointD3D?p1 = null; int i0 = 0; int i1 = 0; if (a1 <= 0) { p0 = PointD3D.Interpolate(_points[0], _points[1], a1 / totLength); i0 = 1; } else { double sum = 0, prevSum = 0; for (int i = 1; i < _points.Length; ++i) { sum += (_points[i] - _points[i - 1]).Length; if (!(sum < a1)) { p0 = PointD3D.Interpolate(_points[i - 1], _points[i], (a1 - prevSum) / (sum - prevSum)); i0 = p0 != _points[i] ? i : i + 1; break; } prevSum = sum; } } if (a2 <= 0) { p1 = PointD3D.Interpolate(_points[_points.Length - 2], _points[_points.Length - 1], 1 - a2 / totLength); i1 = _points.Length - 2; } else { double sum = 0, prevSum = 0; for (int i = _points.Length - 2; i >= 0; --i) { sum += (_points[i] - _points[i + 1]).Length; if (!(sum < a2)) { p1 = PointD3D.Interpolate(_points[i + 1], _points[i], (a2 - prevSum) / (sum - prevSum)); i1 = p1 != _points[i] ? i : i - 1; break; } prevSum = sum; } } if (p0.HasValue && p1.HasValue) { var plist = new List <PointD3D> { p0.Value }; for (int i = i0; i <= i1; ++i) { plist.Add(_points[i]); } plist.Add(p1.Value); return(new SharpPolylineD3D(plist.ToArray())); } else { return(null); } }
public static void Test_GetFractionalPolyline_01() { const double maxDev = 1E-6; string comment = string.Empty; for (int caseNo = 0; caseNo < _testCases.Length; ++caseNo) { if (caseNo == 1 || caseNo == 2) // not with coincidenting points { continue; } var points = _testCases[caseNo].Item1; var expectedOutput = _testCases[caseNo].Item2; var maxEndIndex = points.Length - 1; for (double endIndex = 0.25; endIndex <= maxEndIndex; endIndex += 0.25) { for (double startIndex = 0; startIndex < endIndex; startIndex += 0.25) { var result = PolylineMath3D.GetPolylineWithFractionalStartAndEndIndex( points, expectedOutput[0].Item2, expectedOutput[0].Item3, (points[1] - points[0]).Normalized, startIndex, endIndex, false, false, new PolylinePointD3DAsClass(), false, false, new PolylinePointD3DAsClass()).ToArray(); int iShift = (int)Math.Floor(startIndex); for (int i = (int)Math.Ceiling(startIndex); i < (int)Math.Floor(endIndex); ++i) { comment = string.Format("In case no. {0}, startIndex={1}, endIndex={2}, i={3}", caseNo, startIndex, endIndex, i); Assert.AreEqual(expectedOutput[i].Item1, result[i - iShift].Position, comment); Assert.AreEqual(expectedOutput[i].Item2.X, result[i - iShift].WestVector.X, maxDev, comment); Assert.AreEqual(expectedOutput[i].Item2.Y, result[i - iShift].WestVector.Y, maxDev, comment); Assert.AreEqual(expectedOutput[i].Item2.Z, result[i - iShift].WestVector.Z, maxDev, comment); Assert.AreEqual(expectedOutput[i].Item3.X, result[i - iShift].NorthVector.X, maxDev, comment); Assert.AreEqual(expectedOutput[i].Item3.Y, result[i - iShift].NorthVector.Y, maxDev, comment); Assert.AreEqual(expectedOutput[i].Item3.Z, result[i - iShift].NorthVector.Z, maxDev, comment); } // start int startIndexInt = (int)Math.Floor(startIndex); double startIndexFrac = startIndex - startIndexInt; var expectedStartPoint = startIndexFrac == 0 ? points[startIndexInt] : PointD3D.Interpolate(points[startIndexInt], points[startIndexInt + 1], startIndexFrac); int vecIndex = startIndexFrac == 0 ? startIndexInt : startIndexInt + 1; comment = string.Format("In case no. {0}, startIndex={1}, endIndex={2}", caseNo, startIndex, endIndex); Assert.AreEqual(expectedStartPoint, result[0].Position, comment); Assert.AreEqual(expectedOutput[vecIndex].Item2.X, result[0].WestVector.X, maxDev, comment); Assert.AreEqual(expectedOutput[vecIndex].Item2.Y, result[0].WestVector.Y, maxDev, comment); Assert.AreEqual(expectedOutput[vecIndex].Item2.Z, result[0].WestVector.Z, maxDev, comment); Assert.AreEqual(expectedOutput[vecIndex].Item3.X, result[0].NorthVector.X, maxDev, comment); Assert.AreEqual(expectedOutput[vecIndex].Item3.Y, result[0].NorthVector.Y, maxDev, comment); Assert.AreEqual(expectedOutput[vecIndex].Item3.Z, result[0].NorthVector.Z, maxDev, comment); // end int endIndexInt = (int)Math.Floor(endIndex); double endIndexFrac = endIndex - endIndexInt; var expectedEndPoint = endIndexFrac == 0 ? points[endIndexInt] : PointD3D.Interpolate(points[endIndexInt], points[endIndexInt + 1], endIndexFrac); vecIndex = endIndexFrac == 0 ? endIndexInt : endIndexInt + 1; var resultLast = result[result.Length - 1]; Assert.AreEqual(expectedEndPoint, resultLast.Position, comment); Assert.AreEqual(expectedOutput[vecIndex].Item2.X, resultLast.WestVector.X, maxDev, comment); Assert.AreEqual(expectedOutput[vecIndex].Item2.Y, resultLast.WestVector.Y, maxDev, comment); Assert.AreEqual(expectedOutput[vecIndex].Item2.Z, resultLast.WestVector.Z, maxDev, comment); Assert.AreEqual(expectedOutput[vecIndex].Item3.X, resultLast.NorthVector.X, maxDev, comment); Assert.AreEqual(expectedOutput[vecIndex].Item3.Y, resultLast.NorthVector.Y, maxDev, comment); Assert.AreEqual(expectedOutput[vecIndex].Item3.Z, resultLast.NorthVector.Z, maxDev, comment); // test first returned } } } }