Пример #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="path"></param>
        /// <param name="stylusShape"></param>
        /// <returns></returns>
        public bool HitTest(IEnumerable <Point> path, StylusShape stylusShape)
        {
            // Check the input parameters
            if (path == null)
            {
                throw new System.ArgumentNullException("path");
            }
            if (stylusShape == null)
            {
                throw new System.ArgumentNullException("stylusShape");
            }

            if (IEnumerablePointHelper.GetCount(path) == 0)
            {
                return(false);
            }

            ErasingStroke erasingStroke = new ErasingStroke(stylusShape);

            erasingStroke.MoveTo(path);

            Rect erasingBounds = erasingStroke.Bounds;

            if (erasingBounds.IsEmpty)
            {
                return(false);
            }

            if (erasingBounds.IntersectsWith(this.GetBounds()))
            {
                return(erasingStroke.HitTest(StrokeNodeIterator.GetIterator(this, this.DrawingAttributes)));
            }

            return(false);
        }
Пример #2
0
        /// <summary>
        /// Erases all ink hit by the contour of an erasing stroke
        /// </summary>
        /// <param name="eraserShape">Shape of the eraser</param>
        /// <param name="eraserPath">a path making the spine of the erasing stroke </param>
        public void Erase(IEnumerable <Point> eraserPath, StylusShape eraserShape)
        {
            // Check the input parameters
            if (eraserShape == null)
            {
                throw new System.ArgumentNullException(SR.Get(SRID.SCEraseShape));
            }
            if (eraserPath == null)
            {
                throw new System.ArgumentNullException(SR.Get(SRID.SCErasePath));
            }
            if (IEnumerablePointHelper.GetCount(eraserPath) == 0)
            {
                return;
            }

            ErasingStroke erasingStroke = new ErasingStroke(eraserShape, eraserPath);

            for (int i = 0; i < this.Count; i++)
            {
                Stroke stroke = this[i];

                List <StrokeIntersection> intersections = new List <StrokeIntersection>();
                erasingStroke.EraseTest(StrokeNodeIterator.GetIterator(stroke, stroke.DrawingAttributes), intersections);
                StrokeCollection eraseResult = stroke.Erase(intersections.ToArray());

                UpdateStrokeCollection(stroke, eraseResult, ref i);
            }
        }
Пример #3
0
 /// <summary>
 /// Creates an incremental hit-tester for hit-testing with a shape.
 /// Scenarios: stroke-erasing and point-erasing
 /// </summary>
 /// <param name="eraserShape">shape of the eraser</param>
 /// <returns>an instance of IncrementalStrokeHitTester</returns>
 public IncrementalStrokeHitTester GetIncrementalStrokeHitTester(StylusShape eraserShape)
 {
     if (eraserShape == null)
     {
         throw new System.ArgumentNullException("eraserShape");
     }
     return(new IncrementalStrokeHitTester(this, eraserShape));
 }
Пример #4
0
        /// <summary>
        /// C-tor
        /// </summary>
        /// <param name="strokes">strokes to hit-test for erasing</param>
        /// <param name="eraserShape">erasing shape</param>
        internal IncrementalStrokeHitTester(StrokeCollection strokes, StylusShape eraserShape)
            : base(strokes)
        {
            System.Diagnostics.Debug.Assert(eraserShape != null);

            // Create an ErasingStroke objects that implements the actual hit-testing
            _erasingStroke = new ErasingStroke(eraserShape);
        }
Пример #5
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="nodeShape"></param>
 /// <returns></returns>
 internal static StrokeNodeOperations CreateInstance(StylusShape nodeShape)
 {
     if (nodeShape == null)
     {
         throw new ArgumentNullException("nodeShape");
     }
     if (nodeShape.IsEllipse)
     {
         return new EllipticalNodeOperations(nodeShape);
     }
     return new StrokeNodeOperations(nodeShape);
 }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="nodeShape"></param>
        internal EllipticalNodeOperations(StylusShape nodeShape)
            : base(nodeShape)
        {
            System.Diagnostics.Debug.Assert((nodeShape != null) && nodeShape.IsEllipse);

            _radii = new Size(nodeShape.Width * 0.5, nodeShape.Height * 0.5);

            // All operations with ellipses become simple(r) if transfrom ellipses into circles.
            // Use the max of the radii for the radius of the circle
            _radius = Math.Max(_radii.Width, _radii.Height);

            // Compute ellipse-to-circle and circle-to-elliipse transforms. The former is used
            // in hit-testing operations while the latter is used when computing vertices of
            // a quadrangle connecting two ellipses
            _transform = nodeShape.Transform;
            _nodeShapeToCircle = _transform;

            Debug.Assert(_nodeShapeToCircle.HasInverse, "About to invert a non-invertible transform");
            _nodeShapeToCircle.Invert();
            if (DoubleUtil.AreClose(_radii.Width, _radii.Height))
            {
                _circleToNodeShape = _transform;
            }
            else
            {
                // Reverse the rotation
                if (false == DoubleUtil.IsZero(nodeShape.Rotation))
                {
                    _nodeShapeToCircle.Rotate(-nodeShape.Rotation);
                    Debug.Assert(_nodeShapeToCircle.HasInverse, "Just rotated an invertible transform and produced a non-invertible one");
                }

                // Scale to enlarge
                double sx, sy;
                if (_radii.Width > _radii.Height)
                {
                    sx = 1;
                    sy = _radii.Width / _radii.Height;
                }
                else
                {
                    sx = _radii.Height / _radii.Width;
                    sy = 1;
                }
                _nodeShapeToCircle.Scale(sx, sy);
                Debug.Assert(_nodeShapeToCircle.HasInverse, "Just scaled an invertible transform and produced a non-invertible one");

                _circleToNodeShape = _nodeShapeToCircle;
                _circleToNodeShape.Invert();
            }
        }
Пример #7
0
        /// <summary>
        /// Erase with an eraser with passed in shape
        /// </summary>
        /// <param name="eraserPath">The path to erase</param>
        /// <param name="eraserShape">Shape of the eraser</param>
        /// <returns></returns>
        public StrokeCollection GetEraseResult(IEnumerable <Point> eraserPath, StylusShape eraserShape)
        {
            // Check the input parameters
            if (eraserShape == null)
            {
                throw new System.ArgumentNullException("eraserShape");
            }
            if (eraserPath == null)
            {
                throw new System.ArgumentNullException("eraserPath");
            }

            return(this.Erase(this.EraseTest(eraserPath, eraserShape)));
        }
Пример #8
0
        /// <summary>Hit tests all segments within a contour generated with shape and path</summary>
        /// <param name="shape"></param>
        /// <param name="path"></param>
        /// <returns>StrokeIntersection array for these segments</returns>
        internal StrokeIntersection[] EraseTest(IEnumerable <Point> path, StylusShape shape)
        {
            System.Diagnostics.Debug.Assert(shape != null);
            System.Diagnostics.Debug.Assert(path != null);
            if (IEnumerablePointHelper.GetCount(path) == 0)
            {
                return(Array.Empty <StrokeIntersection>());
            }

            ErasingStroke             erasingStroke = new ErasingStroke(shape, path);
            List <StrokeIntersection> intersections = new List <StrokeIntersection>();

            erasingStroke.EraseTest(StrokeNodeIterator.GetIterator(this, this.DrawingAttributes), intersections);
            return(intersections.ToArray());
        }
Пример #9
0
        /// <summary>
        /// Return all hit strokes that the StylusShape intersects and returns them in a StrokeCollection
        /// </summary>
        private StrokeCollection PointHitTest(Point point, StylusShape shape)
        {
            // Create the collection to return
            StrokeCollection hits = new StrokeCollection();

            for (int i = 0; i < this.Count; i++)
            {
                Stroke stroke = this[i];
                if (stroke.HitTest(new Point[] { point }, shape))
                {
                    hits.Add(stroke);
                }
            }

            return(hits);
        }
Пример #10
0
        /// <summary>
        /// Issue: what's the return value
        /// </summary>
        /// <param name="path"></param>
        /// <param name="stylusShape"></param>
        /// <returns></returns>
        public StrokeCollection HitTest(IEnumerable <Point> path, StylusShape stylusShape)
        {
            // Check the input parameters
            if (stylusShape == null)
            {
                throw new System.ArgumentNullException("stylusShape");
            }
            if (path == null)
            {
                throw new System.ArgumentNullException("path");
            }
            if (IEnumerablePointHelper.GetCount(path) == 0)
            {
                return(new StrokeCollection());
            }

            // validate input
            ErasingStroke erasingStroke = new ErasingStroke(stylusShape, path);
            Rect          erasingBounds = erasingStroke.Bounds;

            if (erasingBounds.IsEmpty)
            {
                return(new StrokeCollection());
            }
            StrokeCollection hits = new StrokeCollection();

            foreach (Stroke stroke in this)
            {
                // samgeo - Presharp issue
                // Presharp gives a warning when get methods might deref a null.  It's complaining
                // here that 'stroke'' could be null, but StrokeCollection never allows nulls to be added
                // so this is not possible
#pragma warning disable 1634, 1691
#pragma warning suppress 6506
                if (erasingBounds.IntersectsWith(stroke.GetBounds()) &&
                    erasingStroke.HitTest(StrokeNodeIterator.GetIterator(stroke, stroke.DrawingAttributes)))
                {
                    hits.Add(stroke);
                }
#pragma warning restore 1634, 1691
            }

            return(hits);
        }
Пример #11
0
        /// <summary>
        /// Returns a Bezier smoothed version of the StylusPoints
        /// </summary>
        /// <returns></returns>
        public StylusPointCollection GetBezierStylusPoints()
        {
            // Since we can't compute Bezier for single point stroke, we should return.
            if (_stylusPoints.Count < 2)
            {
                return(_stylusPoints);
            }

            // Construct the Bezier approximation
            Bezier bezier = new Bezier();

            if (!bezier.ConstructBezierState(_stylusPoints,
                                             DrawingAttributes.FittingError))
            {
                //construction failed, return a clone of the original points
                return(_stylusPoints.Clone());
            }

            double      tolerance   = 0.5;
            StylusShape stylusShape = this.DrawingAttributes.StylusShape;

            if (null != stylusShape)
            {
                Rect   shapeBoundingBox = stylusShape.BoundingBox;
                double min = Math.Min(shapeBoundingBox.Width, shapeBoundingBox.Height);
                tolerance  = Math.Log10(min + min);
                tolerance *= (StrokeCollectionSerializer.AvalonToHimetricMultiplier / 2);
                if (tolerance < 0.5)
                {
                    //don't allow tolerance to drop below .5 or we
                    //can wind up with an huge amount of bezier points
                    tolerance = 0.5;
                }
            }

            List <Point> bezierPoints = bezier.Flatten(tolerance);

            return(GetInterpolatedStylusPoints(bezierPoints));
        }
Пример #12
0
        /// <summary>
        /// Create a point eraser cursor from StylusShape
        /// </summary>
        /// <param name="stylusShape">Eraser Shape</param>
        /// <param name="tranform">Transform</param>
        /// <returns></returns>
        internal static Cursor GetPointEraserCursor(StylusShape stylusShape, Matrix tranform)
        {
            Debug.Assert(DoubleUtil.IsZero(tranform.OffsetX) && DoubleUtil.IsZero(tranform.OffsetY), "The EraserShape cannot be translated.");
            Debug.Assert(tranform.HasInverse, "The transform has to be invertable.");

            // Create a DA with IsHollow being set. A point eraser will be rendered to a hollow stroke.
            DrawingAttributes da = new DrawingAttributes();
            if (stylusShape.GetType() == typeof(RectangleStylusShape))
            {
                da.StylusTip = StylusTip.Rectangle;
            }
            else
            {
                da.StylusTip = StylusTip.Ellipse;
            }

            da.Height = stylusShape.Height;
            da.Width = stylusShape.Width;
            da.Color = Colors.Black;

            if ( !tranform.IsIdentity )
            {
                // Apply the LayoutTransform and/or RenderTransform
                da.StylusTipTransform *= tranform;
            }

            if ( !DoubleUtil.IsZero(stylusShape.Rotation) )
            {
                // Apply the tip rotation
                Matrix rotationMatrix = Matrix.Identity;
                rotationMatrix.Rotate(stylusShape.Rotation);
                da.StylusTipTransform *= rotationMatrix;
            }

            // Forward to GetPenCursor.
            return GetPenCursor(da, true, false/*isRightToLeft*/);
        }
Пример #13
0
        /// <summary>
        /// Erase with an eraser with passed in shape
        /// </summary>
        /// <param name="eraserPath">The path to erase</param>
        /// <param name="eraserShape">Shape of the eraser</param>
        /// <returns></returns>
        public StrokeCollection GetEraseResult(IEnumerable<Point> eraserPath, StylusShape eraserShape)
        {
            // Check the input parameters
            if (eraserShape == null)
            {
                throw new System.ArgumentNullException("eraserShape");
            }
            if (eraserPath == null)
            {
                throw new System.ArgumentNullException("eraserPath");
            }

            return this.Erase(this.EraseTest(eraserPath, eraserShape));
        }
Пример #14
0
        /// <summary>
        /// C-tor
        /// </summary>
        /// <param name="strokes">strokes to hit-test for erasing</param>
        /// <param name="eraserShape">erasing shape</param>
        internal IncrementalStrokeHitTester(StrokeCollection strokes, StylusShape eraserShape)
            : base(strokes)
        {
            System.Diagnostics.Debug.Assert(eraserShape != null);

            // Create an ErasingStroke objects that implements the actual hit-testing
            _erasingStroke = new ErasingStroke(eraserShape);
        }
Пример #15
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="path"></param>
        /// <param name="stylusShape"></param>
        /// <returns></returns>
        public bool HitTest(IEnumerable<Point> path, StylusShape stylusShape)
        {
            // Check the input parameters
            if (path == null)
            {
                throw new System.ArgumentNullException("path");
            }
            if (stylusShape == null)
            {
                throw new System.ArgumentNullException("stylusShape");
            }

            if (IEnumerablePointHelper.GetCount(path) == 0)
            {
                return false;
            }

            ErasingStroke erasingStroke = new ErasingStroke(stylusShape);
            erasingStroke.MoveTo(path);

            Rect erasingBounds = erasingStroke.Bounds;

            if (erasingBounds.IsEmpty)
            {
                return false;
            }

            if (erasingBounds.IntersectsWith(this.GetBounds()))
            {
                return erasingStroke.HitTest(StrokeNodeIterator.GetIterator(this, this.DrawingAttributes));
            }

            return false;
        }
Пример #16
0
        /// <summary>Hit tests all segments within a contour generated with shape and path</summary>
        /// <param name="shape"></param>
        /// <param name="path"></param>
        /// <returns>StrokeIntersection array for these segments</returns>
        internal StrokeIntersection[] EraseTest(IEnumerable<Point> path, StylusShape shape)
        {
            System.Diagnostics.Debug.Assert(shape != null);
            System.Diagnostics.Debug.Assert(path != null);
            if (IEnumerablePointHelper.GetCount(path) == 0)
            {
                return new StrokeIntersection[0];
            }

            ErasingStroke erasingStroke = new ErasingStroke(shape, path);
            List<StrokeIntersection> intersections = new List<StrokeIntersection>();
            erasingStroke.EraseTest(StrokeNodeIterator.GetIterator(this, this.DrawingAttributes), intersections);
            return intersections.ToArray();
        }
Пример #17
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="nodeShape">shape of the nodes</param>
 internal StrokeNodeOperations(StylusShape nodeShape)
 {
     System.Diagnostics.Debug.Assert(nodeShape != null);
     _vertices = nodeShape.GetVerticesAsVectors();
 }
 public bool HitTest(IEnumerable<System.Windows.Point> path, StylusShape stylusShape)
 {
   return default(bool);
 }
 public IncrementalStrokeHitTester GetIncrementalStrokeHitTester(StylusShape eraserShape)
 {
     return(default(IncrementalStrokeHitTester));
 }
 public void Erase(IEnumerable <System.Windows.Point> eraserPath, StylusShape eraserShape)
 {
 }
 public System.Windows.Ink.StrokeCollection HitTest(IEnumerable <System.Windows.Point> path, StylusShape stylusShape)
 {
     return(default(System.Windows.Ink.StrokeCollection));
 }
Пример #22
0
 public StrokeCollection GetEraseResult(IEnumerable <System.Windows.Point> eraserPath, StylusShape eraserShape)
 {
     return(default(StrokeCollection));
 }
Пример #23
0
 /// <summary>
 /// Constructor for an incremental node enumerator that builds nodes
 /// from array(s) of points and a given stylus shape.
 /// </summary>
 /// <param name="nodeShape">a shape that defines the stroke contour</param>
 internal StrokeNodeIterator(StylusShape nodeShape) 
     : this( null,   //stylusPoints
             StrokeNodeOperations.CreateInstance(nodeShape),
             false)  //usePressure)
 {
 }
Пример #24
0
 /// <summary>
 /// Constructor for incremental erasing
 /// </summary>
 /// <param name="erasingShape">The shape of the eraser's tip</param>
 internal ErasingStroke(StylusShape erasingShape)
 {
     System.Diagnostics.Debug.Assert(erasingShape != null);
     _nodeIterator = new StrokeNodeIterator(erasingShape);
 }
 public StrokeCollection GetEraseResult(IEnumerable<System.Windows.Point> eraserPath, StylusShape eraserShape)
 {
   return default(StrokeCollection);
 }
Пример #26
0
 public bool HitTest(IEnumerable <System.Windows.Point> path, StylusShape stylusShape)
 {
     return(default(bool));
 }
Пример #27
0
 /// <summary>
 /// Constructor for static (atomic) erasing
 /// </summary>
 /// <param name="erasingShape">The shape of the eraser's tip</param>
 /// <param name="path">the spine of the erasing stroke</param>
 internal ErasingStroke(StylusShape erasingShape, IEnumerable<Point> path)
     : this(erasingShape)
 {
     MoveTo(path);
 }