File: Core\CSharp\MS\Internal\Ink\StrokeIntersection.cs
Project: wpf\src\PresentationCore.csproj (PresentationCore)
//-----------------------------------------------------------------------
// <copyright file="StrokeIntersection.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
using MS.Internal;
using MS.Internal.Ink;
using MS.Utility;
using System;
using System.Windows;
using System.Collections.Generic;
using System.Globalization;
 
namespace System.Windows.Ink
{
    /// <summary>
    /// A helper struct that represents a fragment of a stroke spine.
    /// </summary>
    internal struct StrokeIntersection
    {
 
        #region Private statics
        private static StrokeIntersection s_empty = new StrokeIntersection(AfterLast, AfterLast, BeforeFirst, BeforeFirst);
        private static StrokeIntersection s_full = new StrokeIntersection(BeforeFirst, BeforeFirst, AfterLast, AfterLast);
        #endregion
 
        #region Public API
 
        /// <summary>
        /// BeforeFirst
        /// </summary>
        /// <value></value>
        internal static double BeforeFirst { get { return StrokeFIndices.BeforeFirst; } }
 
        /// <summary>
        /// AfterLast
        /// </summary>
        /// <value></value>
        internal static double AfterLast { get { return StrokeFIndices.AfterLast; } }
 
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="hitBegin"></param>
        /// <param name="inBegin"></param>
        /// <param name="inEnd"></param>
        /// <param name="hitEnd"></param>
        internal StrokeIntersection(double hitBegin, double inBegin, double inEnd, double hitEnd)
        {
            //ISSUE-2004/12/06-XiaoTu: should we validate the input?
            _hitSegment = new StrokeFIndices(hitBegin, hitEnd);
            _inSegment = new StrokeFIndices(inBegin, inEnd);
        }
 
        /// <summary>
        /// hitBeginFIndex
        /// </summary>
        /// <value></value>
        internal double HitBegin
        {
            set { _hitSegment.BeginFIndex = value; }
        }
 
        /// <summary>
        /// hitEndFIndex
        /// </summary>
        /// <value></value>
        internal double HitEnd
        {
            get { return _hitSegment.EndFIndex; }
            set { _hitSegment.EndFIndex = value; }
        }
 
 
        /// <summary>
        /// InBegin
        /// </summary>
        /// <value></value>
        internal double InBegin
        {
            get { return _inSegment.BeginFIndex; }
            set { _inSegment.BeginFIndex = value; }
        }
 
        /// <summary>
        /// InEnd
        /// </summary>
        /// <value></value>
        internal double InEnd
        {
            get { return _inSegment.EndFIndex; }
            set { _inSegment.EndFIndex = value; }
        }
 
        /// <summary>
        /// ToString
        /// </summary>
        public override string ToString()
        {
            return "{"  + StrokeFIndices.GetStringRepresentation(_hitSegment.BeginFIndex) + ","
                        + StrokeFIndices.GetStringRepresentation(_inSegment.BeginFIndex)  + ","
                        + StrokeFIndices.GetStringRepresentation(_inSegment.EndFIndex)    + ","
                        + StrokeFIndices.GetStringRepresentation(_hitSegment.EndFIndex)   + "}";
        }
 
 
        /// <summary>
        /// Equals
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(Object obj)
        {
            // Check for null and compare run-time types
            if (obj == null || GetType() != obj.GetType())
                return false;
            return ((StrokeIntersection)obj == this);
        }
 
        /// <summary>
        /// GetHashCode
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            return _hitSegment.GetHashCode() ^ _inSegment.GetHashCode();
        }
 
 
        /// <summary>
        /// operator ==
        /// </summary>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <returns></returns>
        public static bool operator ==(StrokeIntersection left, StrokeIntersection right)
        {
            return (left._hitSegment == right._hitSegment && left._inSegment == right._inSegment);
        }
 
        /// <summary>
        /// operator !=
        /// </summary>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <returns></returns>
        public static bool operator !=(StrokeIntersection left, StrokeIntersection right)
        {
            return !(left == right);
        }
 
        #endregion
 
        #region Internal API
 
        /// <summary>
        ///
        /// </summary>
        internal static StrokeIntersection Full { get { return s_full; } }
 
        /// <summary>
        ///
        /// </summary>
        internal bool IsEmpty { get { return _hitSegment.IsEmpty; } }
 
 
        /// <summary>
        ///
        /// </summary>
        internal StrokeFIndices HitSegment
        {
            get { return _hitSegment; }
        }
 
        /// <summary>
        ///
        /// </summary>
        internal StrokeFIndices InSegment
        {
            get { return _inSegment; }
        }
 
        #endregion
 
        #region Internal static methods
 
        /// <summary>
        /// Get the "in-segments" of the intersections.
        /// </summary>
        internal static StrokeFIndices[] GetInSegments(StrokeIntersection[] intersections)
        {
            System.Diagnostics.Debug.Assert(intersections != null);
            System.Diagnostics.Debug.Assert(intersections.Length > 0);
 
            List<StrokeFIndices> inFIndices = new List<StrokeFIndices>(intersections.Length);
            for (int j = 0; j < intersections.Length; j++)
            {
                System.Diagnostics.Debug.Assert(!intersections[j].IsEmpty);
                if (!intersections[j].InSegment.IsEmpty)
                {
                    if (inFIndices.Count > 0 &&
                        inFIndices[inFIndices.Count - 1].EndFIndex >=
                        intersections[j].InSegment.BeginFIndex)
                    {
                        //merge
                        StrokeFIndices sfiPrevious = inFIndices[inFIndices.Count - 1];
                        sfiPrevious.EndFIndex = intersections[j].InSegment.EndFIndex;
                        inFIndices[inFIndices.Count - 1] = sfiPrevious;
                    }
                    else
                    {
                        inFIndices.Add(intersections[j].InSegment);
                    }
                }
            }
            return inFIndices.ToArray();
        }
 
        /// <summary>
        /// Get the "hit-segments"
        /// </summary>
        internal static StrokeFIndices[] GetHitSegments(StrokeIntersection[] intersections)
        {
            System.Diagnostics.Debug.Assert(intersections != null);
            System.Diagnostics.Debug.Assert(intersections.Length > 0);
 
            List<StrokeFIndices> hitFIndices = new List<StrokeFIndices>(intersections.Length);
            for (int j = 0; j < intersections.Length; j++)
            {
                System.Diagnostics.Debug.Assert(!intersections[j].IsEmpty);
                if (!intersections[j].HitSegment.IsEmpty)
                {
                    if (hitFIndices.Count > 0 &&
                        hitFIndices[hitFIndices.Count - 1].EndFIndex >=
                        intersections[j].HitSegment.BeginFIndex)
                    {
                        //merge
                        StrokeFIndices sfiPrevious = hitFIndices[hitFIndices.Count - 1];
                        sfiPrevious.EndFIndex = intersections[j].HitSegment.EndFIndex;
                        hitFIndices[hitFIndices.Count - 1] = sfiPrevious;
                    }
                    else
                    {
                        hitFIndices.Add(intersections[j].HitSegment);
                    }
                }
            }
            return hitFIndices.ToArray();
        }
 
        #endregion
 
        #region  Fields
 
        private StrokeFIndices _hitSegment;
        private StrokeFIndices _inSegment;
 
        #endregion
    }
}