/// <summary> /// Check whether a certain percentage of the stroke is within the lasso /// </summary> /// <param name="lassoPoints"></param> /// <param name="percentageWithinLasso"></param> /// <returns></returns> public bool HitTest(IEnumerable <Point> lassoPoints, int percentageWithinLasso) { if (lassoPoints == null) { throw new System.ArgumentNullException("lassoPoints"); } if ((percentageWithinLasso < 0) || (percentageWithinLasso > 100)) { throw new System.ArgumentOutOfRangeException("percentageWithinLasso"); } if (percentageWithinLasso == 0) { return(true); } StrokeInfo strokeInfo = null; try { strokeInfo = new StrokeInfo(this); StylusPointCollection stylusPoints = strokeInfo.StylusPoints; double target = strokeInfo.TotalWeight * percentageWithinLasso / 100.0f - PercentageTolerance; Lasso lasso = new SingleLoopLasso(); lasso.AddPoints(lassoPoints); for (int i = 0; i < stylusPoints.Count; i++) { if (true == lasso.Contains((Point)stylusPoints[i])) { target -= strokeInfo.GetPointWeight(i); if (DoubleUtil.LessThan(target, 0f)) { return(true); } } } return(false); } finally { if (strokeInfo != null) { //detach from event handlers, or else we leak. strokeInfo.Detach(); } } }
/// <summary> /// IHT's can get into a state where their StrokeInfo cache is too /// out of sync with the StrokeCollection to incrementally update it. /// When we detect this has happened, we just rebuild the entire cache. /// </summary> private void RebuildStrokeInfoCache() { List <StrokeInfo> newStrokeInfos = new List <StrokeInfo>(_strokes.Count); foreach (Stroke stroke in _strokes) { bool found = false; for (int x = 0; x < _strokeInfos.Count; x++) { StrokeInfo strokeInfo = _strokeInfos[x]; if (strokeInfo != null && stroke == strokeInfo.Stroke) { newStrokeInfos.Add(strokeInfo); //just set to null instead of removing and shifting //we're about to GC _strokeInfos _strokeInfos[x] = null; found = true; break; } } if (!found) { //we didn't find an existing strokeInfo newStrokeInfos.Add(new StrokeInfo(stroke)); } } //detach the remaining strokeInfo's from their strokes for (int x = 0; x < _strokeInfos.Count; x++) { StrokeInfo strokeInfo = _strokeInfos[x]; if (strokeInfo != null) { strokeInfo.Detach(); } } _strokeInfos = newStrokeInfos; #if DEBUG Debug.Assert(_strokeInfos.Count == _strokes.Count); for (int x = 0; x < _strokeInfos.Count; x++) { Debug.Assert(_strokeInfos[x].Stroke == _strokes[x]); } #endif }
/// <summary> /// Check whether a certain percentage of the stroke is within the Rect passed in. /// </summary> /// <param name="bounds"></param> /// <param name="percentageWithinBounds"></param> /// <returns></returns> public bool HitTest(Rect bounds, int percentageWithinBounds) { if ((percentageWithinBounds < 0) || (percentageWithinBounds > 100)) { throw new System.ArgumentOutOfRangeException("percentageWithinBounds"); } if (percentageWithinBounds == 0) { return(true); } StrokeInfo strokeInfo = null; try { strokeInfo = new StrokeInfo(this); StylusPointCollection stylusPoints = strokeInfo.StylusPoints; double target = strokeInfo.TotalWeight * percentageWithinBounds / 100.0f - PercentageTolerance; for (int i = 0; i < stylusPoints.Count; i++) { if (true == bounds.Contains((Point)stylusPoints[i])) { target -= strokeInfo.GetPointWeight(i); if (DoubleUtil.LessThanOrClose(target, 0d)) { return(true); } } } return(false); } finally { if (strokeInfo != null) { //detach from event handlers, or else we leak. strokeInfo.Detach(); } } }
/// <summary> /// Hit-testing with lasso /// </summary> /// <param name="lassoPoints">points making the lasso</param> /// <param name="percentageWithinLasso">the margin value to tell whether a stroke /// is in or outside of the rect</param> /// <returns>collection of strokes found inside the rectangle</returns> public StrokeCollection HitTest(IEnumerable <Point> lassoPoints, int percentageWithinLasso) { // Check the input parameters if (lassoPoints == null) { throw new System.ArgumentNullException("lassoPoints"); } if ((percentageWithinLasso < 0) || (percentageWithinLasso > 100)) { throw new System.ArgumentOutOfRangeException("percentageWithinLasso"); } if (IEnumerablePointHelper.GetCount(lassoPoints) < 3) { return(new StrokeCollection()); } Lasso lasso = new SingleLoopLasso(); lasso.AddPoints(lassoPoints); // Enumerate through the strokes and collect those captured by the lasso. StrokeCollection lassoedStrokes = new StrokeCollection(); foreach (Stroke stroke in this) { if (percentageWithinLasso == 0) { lassoedStrokes.Add(stroke); } else { StrokeInfo strokeInfo = null; try { strokeInfo = new StrokeInfo(stroke); StylusPointCollection stylusPoints = strokeInfo.StylusPoints; double target = strokeInfo.TotalWeight * percentageWithinLasso / 100.0f - Stroke.PercentageTolerance; for (int i = 0; i < stylusPoints.Count; i++) { if (true == lasso.Contains((Point)stylusPoints[i])) { target -= strokeInfo.GetPointWeight(i); if (DoubleUtil.LessThanOrClose(target, 0f)) { lassoedStrokes.Add(stroke); break; } } } } finally { if (strokeInfo != null) { //detach from event handlers, or else we leak. strokeInfo.Detach(); } } } } // Return the resulting collection return(lassoedStrokes); }