/// <summary> /// The implementation behind the public methods AddPoint/AddPoints /// </summary> /// <param name="points">new points to add to the lasso</param> protected override void AddPointsCore(IEnumerable<Point> points) { System.Diagnostics.Debug.Assert((points != null) && (IEnumerablePointHelper.GetCount(points)!= 0)); // Add the new points to the lasso int lastPointIndex = (0 != _lasso.PointCount) ? (_lasso.PointCount - 1) : 0; _lasso.AddPoints(points); // Do nothing if there's not enough points, or there's nobody listening // The points may be filtered out, so if all the points are filtered out, (lastPointIndex == (_lasso.PointCount - 1). // For this case, check if the incremental lasso is disabled (i.e., points modified). if ((_lasso.IsEmpty) || (lastPointIndex == (_lasso.PointCount - 1) && false == _lasso.IsIncrementalLassoDirty) || (SelectionChanged == null)) { return; } // Variables for possible HitChanged events to fire StrokeCollection strokesHit = null; StrokeCollection strokesUnhit = null; // Create a lasso that represents the current increment Lasso lassoUpdate = new Lasso(); if (false == _lasso.IsIncrementalLassoDirty) { if (0 < lastPointIndex) { lassoUpdate.AddPoint(_lasso[0]); } // Only the points the have been successfully added to _lasso will be added to // lassoUpdate. for (; lastPointIndex < _lasso.PointCount; lastPointIndex++) { lassoUpdate.AddPoint(_lasso[lastPointIndex]); } } // Enumerate through the strokes and update their hit-test results foreach (StrokeInfo strokeInfo in this.StrokeInfos) { Lasso lasso; if (true == strokeInfo.IsDirty || true == _lasso.IsIncrementalLassoDirty) { // If this is the first time this stroke gets hit-tested with this lasso, // or if the stroke (or its DAs) has changed since the last hit-testing, // or if the lasso points have been modified, // then (re)hit-test this stroke against the entire lasso. lasso = _lasso; strokeInfo.IsDirty = false; } else { // Otherwise, hit-test it against the lasso increment first and then only // those ink points that are in that small lasso need to be hit-tested // against the big (entire) lasso. // This is supposed to be a significant piece of optimization, since // lasso increments are usually very small, they are defined by just // a few points and they don't capture and/or release too many ink nodes. lasso = lassoUpdate; } // Skip those stroke which bounding box doesn't even intersects with the lasso bounds double hitWeightChange = 0f; if (lasso.Bounds.IntersectsWith(strokeInfo.StrokeBounds)) { // Get the stroke node points for the hit-testing. StylusPointCollection stylusPoints = strokeInfo.StylusPoints; // Find out if the lasso update has changed the hit count of the stroke. for (int i = 0; i < stylusPoints.Count; i++) { // Consider only the points that become captured/released with this particular update if (true == lasso.Contains((Point)stylusPoints[i])) { double weight = strokeInfo.GetPointWeight(i); if (lasso == _lasso || _lasso.Contains((Point)stylusPoints[i])) { hitWeightChange += weight; } else { hitWeightChange -= weight; } } } } // Update the stroke hit weight and check whether it has crossed the margin // in either direction since the last update. if ((hitWeightChange != 0) || (lasso == _lasso)) { strokeInfo.HitWeight = (lasso == _lasso) ? hitWeightChange : (strokeInfo.HitWeight + hitWeightChange); bool isHit = DoubleUtil.GreaterThanOrClose(strokeInfo.HitWeight, strokeInfo.TotalWeight * _percentIntersect / 100f - Stroke.PercentageTolerance); if (strokeInfo.IsHit != isHit) { strokeInfo.IsHit = isHit; if (isHit) { // The hit count became greater than the margin percentage, the stroke // needs to be reported for selection if (null == strokesHit) { strokesHit = new StrokeCollection(); } strokesHit.Add(strokeInfo.Stroke); } else { // The hit count just became less than the margin percentage, // the stroke needs to be reported for de-selection if (null == strokesUnhit) { strokesUnhit = new StrokeCollection(); } strokesUnhit.Add(strokeInfo.Stroke); } } } } _lasso.IsIncrementalLassoDirty = false; // Raise StrokesHitChanged event if any strokes has changed thier // hit status and there're the event subscribers. if ((null != strokesHit) || (null != strokesUnhit)) { OnSelectionChanged(new LassoSelectionChangedEventArgs (strokesHit, strokesUnhit)); } }
/// <summary> /// Hit tests all segments within the lasso loops /// </summary> /// <returns> a StrokeIntersection array for these segments</returns> internal StrokeIntersection[] HitTest(Lasso lasso) { // Check the input parameters System.Diagnostics.Debug.Assert(lasso != null); if (lasso.IsEmpty) { return new StrokeIntersection[0]; } // The following will check whether all the points are within the lasso. // If yes, return the whole stroke as being hit. if (!lasso.Bounds.IntersectsWith(this.GetBounds())) { return new StrokeIntersection[0]; } return lasso.HitTest(StrokeNodeIterator.GetIterator(this, this.DrawingAttributes)); }