File: System.Activities.Presentation\System\Activities\Presentation\FreeFormEditing\ConnectorPointsToSegmentsConverter.cs
Project: ndp\cdf\src\NetFx40\Tools\System.Activities.Presentation.csproj (System.Activities.Presentation)
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------
 
namespace System.Activities.Presentation.FreeFormEditing
{
    using System;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Media;
    using System.Diagnostics.CodeAnalysis;
 
    [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Justification = "The class is used in xaml.")]
    class ConnectorPointsToSegmentsConverter : IValueConverter
    {
        const double RoundRadius = 4.0;
 
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            PathSegmentCollection retVal = new PathSegmentCollection();
            PointCollection pointCollection = value as PointCollection;
            if (RoundRadius > 0)
            {
                if (pointCollection != null && pointCollection.Count > 0)
                {
                    retVal.Add(new LineSegment(pointCollection[0], true));
                    double curSegmentArcUsed = 0;
                    for (int i = 1; i < pointCollection.Count - 1; i++)
                    {
                        double dist1 = DesignerGeometryHelper.DistanceBetweenPoints(pointCollection[i - 1], pointCollection[i]);
                        double dist2 = DesignerGeometryHelper.DistanceBetweenPoints(pointCollection[i], pointCollection[i + 1]);
                        if (dist1 - curSegmentArcUsed > RoundRadius &&
                            dist2 > RoundRadius)
                        {
                            //build rounded arc at line join.
                            curSegmentArcUsed = RoundRadius;
                            Vector firstSegmentPointingVector = new Vector(pointCollection[i].X - pointCollection[i - 1].X, pointCollection[i].Y - pointCollection[i - 1].Y);
                            Vector secondSegmentPointingVector = new Vector(pointCollection[i + 1].X - pointCollection[i].X, pointCollection[i + 1].Y - pointCollection[i].Y);
                            firstSegmentPointingVector.Normalize();
                            secondSegmentPointingVector.Normalize();
                            Point turningPoint1 = Point.Add(pointCollection[i - 1], Vector.Multiply(dist1 - RoundRadius, firstSegmentPointingVector));
                            Point turningPoint2 = Point.Add(pointCollection[i], Vector.Multiply(RoundRadius, secondSegmentPointingVector));
                            double crossProductZ = firstSegmentPointingVector.X * secondSegmentPointingVector.Y - firstSegmentPointingVector.Y * secondSegmentPointingVector.X;
                            retVal.Add(new LineSegment(turningPoint1, true));
                            retVal.Add(new ArcSegment(turningPoint2, new Size(RoundRadius, RoundRadius), 0, false, crossProductZ > 0 ? SweepDirection.Clockwise : SweepDirection.Counterclockwise, true));
                        }
                        else
                        {
                            curSegmentArcUsed = 0;
                            retVal.Add(new LineSegment(pointCollection[i], true));
                        }
                    }
                    retVal.Add(new LineSegment(pointCollection[pointCollection.Count - 1], true));
                }
            }
            return retVal;
        }
 
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw FxTrace.Exception.AsError(new NotSupportedException());
        }
 
    }
}