示例#1
0
文件: Lasso.cs 项目: beda2280/wpf-1
        /// <summary>
        /// Sort and merge the crossing list
        /// </summary>
        /// <param name="crossingList">The crossing list to sort/merge</param>
        private static void SortAndMerge(ref List <LassoCrossing> crossingList)
        {
            // Sort the crossings based on the BeginFIndex values
            crossingList.Sort();

            List <LassoCrossing> mergedList = new List <LassoCrossing>();
            LassoCrossing        mcrossing  = LassoCrossing.EmptyCrossing;

            foreach (LassoCrossing crossing in crossingList)
            {
                System.Diagnostics.Debug.Assert(!crossing.IsEmpty && crossing.StartNode.IsValid && crossing.EndNode.IsValid);
                if (!mcrossing.Merge(crossing))
                {
                    System.Diagnostics.Debug.Assert(!mcrossing.IsEmpty && mcrossing.StartNode.IsValid && mcrossing.EndNode.IsValid);
                    mergedList.Add(mcrossing);
                    mcrossing = crossing;
                }
            }
            if (!mcrossing.IsEmpty)
            {
                System.Diagnostics.Debug.Assert(!mcrossing.IsEmpty && mcrossing.StartNode.IsValid && mcrossing.EndNode.IsValid);
                mergedList.Add(mcrossing);
            }
            crossingList = mergedList;
        }
示例#2
0
文件: Lasso.cs 项目: beda2280/wpf-1
        internal StrokeIntersection[] HitTest(StrokeNodeIterator iterator)
        {
            System.Diagnostics.Debug.Assert(_points != null);
            System.Diagnostics.Debug.Assert(iterator != null);

            if (_points.Count < 3)
            {
                //
                // it takes at least 3 points to create a lasso
                //
                return(Array.Empty <StrokeIntersection>());
            }

            //
            // We're about to perform hit testing with a lasso.
            // To do so we need to iterate through each StrokeNode.
            // As we do, we calculate the bounding rect between it
            // and the previous StrokeNode and store this in 'currentStrokeSegmentBounds'
            //
            // Next, we check to see if that StrokeNode pair's bounding box intersects
            // with the bounding box of the Lasso points.  If not, we continue iterating through
            // StrokeNode pairs.
            //
            // If it does, we do a more granular hit test by pairing points in the Lasso, getting
            // their bounding box and seeing if that bounding box intersects our current StrokeNode
            // pair
            //

            Point lastNodePosition           = new Point();
            Point lassoLastPoint             = _points[_points.Count - 1];
            Rect  currentStrokeSegmentBounds = Rect.Empty;

            // Initilize the current crossing to be an empty one
            LassoCrossing currentCrossing = LassoCrossing.EmptyCrossing;

            // Creat a list to hold all the crossings
            List <LassoCrossing> crossingList = new List <LassoCrossing>();

            for (int i = 0; i < iterator.Count; i++)
            {
                StrokeNode strokeNode = iterator[i];
                Rect       nodeBounds = strokeNode.GetBounds();
                currentStrokeSegmentBounds.Union(nodeBounds);

                // Skip the node if it's outside of the lasso's bounds
                if (currentStrokeSegmentBounds.IntersectsWith(_bounds) == true)
                {
                    // currentStrokeSegmentBounds, made up of the bounding box of
                    // this StrokeNode unioned with the last StrokeNode,
                    // intersects the lasso bounding box.
                    //
                    // Now we need to iterate through the lasso points and find out where they cross
                    //
                    Point lastPoint = lassoLastPoint;
                    foreach (Point point in _points)
                    {
                        //
                        // calculate a segment of the lasso from the last point
                        // to the current point
                        //
                        Rect lassoSegmentBounds = new Rect(lastPoint, point);

                        //
                        // see if this lasso segment intersects with the current stroke segment
                        //
                        if (!currentStrokeSegmentBounds.IntersectsWith(lassoSegmentBounds))
                        {
                            lastPoint = point;
                            continue;
                        }

                        //
                        // the lasso segment DOES intersect with the current stroke segment
                        // find out precisely where
                        //
                        StrokeFIndices strokeFIndices = strokeNode.CutTest(lastPoint, point);

                        lastPoint = point;
                        if (strokeFIndices.IsEmpty)
                        {
                            // current lasso segment does not hit the stroke segment, continue with the next lasso point
                            continue;
                        }

                        // Create a potentially new crossing for the current hit testing result.
                        LassoCrossing potentialNewCrossing = new LassoCrossing(strokeFIndices, strokeNode);

                        // Try to merge with the current crossing. If the merge is succussful (return true), the new crossing is actually
                        // continueing the current crossing, so do not start a new crossing. Otherwise, start a new one and add the existing
                        // one to the list.
                        if (!currentCrossing.Merge(potentialNewCrossing))
                        {
                            // start a new crossing and add the existing on to the list
                            crossingList.Add(currentCrossing);
                            currentCrossing = potentialNewCrossing;
                        }
                    }
                }

                // Continue with the next node
                currentStrokeSegmentBounds = nodeBounds;
                lastNodePosition           = strokeNode.Position;
            }


            // Adding the last crossing to the list, if valid
            if (!currentCrossing.IsEmpty)
            {
                crossingList.Add(currentCrossing);
            }

            // Handle the special case of no intersection at all
            if (crossingList.Count == 0)
            {
                // the stroke was either completely inside the lasso
                // or outside the lasso
                if (this.Contains(lastNodePosition))
                {
                    StrokeIntersection[] strokeIntersections = new StrokeIntersection[1];
                    strokeIntersections[0] = StrokeIntersection.Full;
                    return(strokeIntersections);
                }
                else
                {
                    return(Array.Empty <StrokeIntersection>());
                }
            }

            // It is still possible that the current crossing list is not sorted or overlapping.
            // Sort the list and merge the overlapping ones.
            SortAndMerge(ref crossingList);

            // Produce the hit test results and store them in a list
            List <StrokeIntersection> strokeIntersectionList = new List <StrokeIntersection>();

            ProduceHitTestResults(crossingList, strokeIntersectionList);

            return(strokeIntersectionList.ToArray());
        }