/// <summary> /// Optimize specified shape. /// </summary> /// /// <param name="shape">Shape to be optimized.</param> /// /// <returns>Returns final optimized shape, which may have reduced amount of points.</returns> /// public List <IntPoint> OptimizeShape(List <IntPoint> shape) { // optimized shape List <IntPoint> optimizedShape = new List <IntPoint>( ); // list of recently removed points List <IntPoint> recentlyRemovedPoints = new List <IntPoint>( ); if (shape.Count <= 3) { // do nothing if shape has 3 points or less optimizedShape.AddRange(shape); } else { double distance = 0; // add first 2 points to the new shape optimizedShape.Add(shape[0]); optimizedShape.Add(shape[1]); int pointsInOptimizedHull = 2; for (int i = 2, n = shape.Count; i < n; i++) { // add new point optimizedShape.Add(shape[i]); pointsInOptimizedHull++; // add new candidate for removing to the list recentlyRemovedPoints.Add(optimizedShape[pointsInOptimizedHull - 2]); // calculate maximum distance between new candidate line and recently removed point PointsCloud.GetFurthestPointFromLine(recentlyRemovedPoints, optimizedShape[pointsInOptimizedHull - 3], optimizedShape[pointsInOptimizedHull - 1], out distance); if ((distance <= maxDistanceToRemove) && ((pointsInOptimizedHull > 3) || (i < n - 1))) { optimizedShape.RemoveAt(pointsInOptimizedHull - 2); pointsInOptimizedHull--; } else { // don't need to remove the last candidate point recentlyRemovedPoints.Clear( ); } } if (pointsInOptimizedHull > 3) { // check the last point recentlyRemovedPoints.Add(optimizedShape[pointsInOptimizedHull - 1]); PointsCloud.GetFurthestPointFromLine(recentlyRemovedPoints, optimizedShape[pointsInOptimizedHull - 2], optimizedShape[0], out distance); if (distance <= maxDistanceToRemove) { optimizedShape.RemoveAt(pointsInOptimizedHull - 1); pointsInOptimizedHull--; } else { recentlyRemovedPoints.Clear( ); } if (pointsInOptimizedHull > 3) { // check the first point recentlyRemovedPoints.Add(optimizedShape[0]); PointsCloud.GetFurthestPointFromLine(recentlyRemovedPoints, optimizedShape[pointsInOptimizedHull - 1], optimizedShape[1], out distance); if (distance <= maxDistanceToRemove) { optimizedShape.RemoveAt(0); } } } } return(optimizedShape); }