IEnumerable<Shape> RecognizeScribbleForEraseOrCancel(DragState state, out bool cancel, out List<PointT> simplifiedSS)
{
cancel = false;
simplifiedSS = null;
var tolerance = state._inputTransform.Transform(new VectorT(0, 10)).Length();
var simplifiedMP = LineMath.SimplifyPolyline(
state.UnfilteredMousePoints.Select(p => p.Point), tolerance);
List<int> reversals = FindReversals(simplifiedMP, 3);
if (reversals.Count >= 3)
{
simplifiedSS = simplifiedMP.Select(p => state._inputTransform.Transform(p)).ToList();
// 3 reversals confirmed. Now decide: erase or cancel?
int[] timeStampsMs = FindTimeStamps(state.UnfilteredMousePoints, simplifiedMP);
int t0 = timeStampsMs[reversals[0]], t1 = timeStampsMs[reversals[2]] - t0;
cancel = t0 > t1 + 500;
// Now test the formula LL*c > CHA as explained above
IListSource<PointT> simplifiedMP_ = cancel ? simplifiedMP.Slice(reversals[0]) : simplifiedMP.AsListSource();
float LL = simplifiedMP_.AdjacentPairs().Sum(pair => pair.A.Sub(pair.B).Length());
var hull = PointMath.ComputeConvexHull(simplifiedMP);
float CHA = PolygonMath.PolygonArea(hull);
if (LL * EraseNubWidth > CHA)
{
// Erasure confirmed.
if (cancel)
return EmptyList<Shape>.Value;
// Figure out which shapes to erase. To do this, we compute for
// each shape the amount of the scribble that overlaps that shape.
var simplifiedSS_ = simplifiedSS;
return _doc.Shapes.Where(s => ShouldErase(s, simplifiedSS_)).ToList();
}
}
return null;
}