Пример #1
0
        internal ConnectorModel GetInfo()
        {
            var owner = new DesignerItemModel();
            owner.Left = DesignerCanvas.GetLeft( ParentDesignerItem );
            owner.Top = DesignerCanvas.GetTop( ParentDesignerItem );
            owner.Size = new Size( ParentDesignerItem.ActualWidth, ParentDesignerItem.ActualHeight );

            ConnectorModel info = new ConnectorModel( owner );
            info.Orientation = Orientation;
            info.Position = Position;

            return info;
        }
        private static Point GetOffsetPoint( ConnectorModel connector, Rect rect )
        {
            Point offsetPoint = new Point();

            switch ( connector.Orientation )
            {
                case ConnectorOrientation.Left:
                    offsetPoint = new Point( rect.Left, connector.Position.Y );
                    break;
                case ConnectorOrientation.Top:
                    offsetPoint = new Point( connector.Position.X, rect.Top );
                    break;
                case ConnectorOrientation.Right:
                    offsetPoint = new Point( rect.Right, connector.Position.Y );
                    break;
                case ConnectorOrientation.Bottom:
                    offsetPoint = new Point( connector.Position.X, rect.Bottom );
                    break;
                default:
                    break;
            }

            return offsetPoint;
        }
        private static void CheckPathEnd( ConnectorModel source, ConnectorModel sink, bool showLastLine, List<Point> linePoints )
        {
            if ( showLastLine )
            {
                Point startPoint = new Point( 0, 0 );
                switch ( source.Orientation )
                {
                    case ConnectorOrientation.Left:
                        startPoint = new Point( source.Position.X - PathMargin, source.Position.Y );
                        break;
                    case ConnectorOrientation.Top:
                        startPoint = new Point( source.Position.X, source.Position.Y - PathMargin );
                        break;
                    case ConnectorOrientation.Right:
                        startPoint = new Point( source.Position.X + PathMargin, source.Position.Y );
                        break;
                    case ConnectorOrientation.Bottom:
                        startPoint = new Point( source.Position.X, source.Position.Y + PathMargin );
                        break;
                    default:
                        break;
                }

                Point endPoint = new Point( 0, 0 );
                switch ( sink.Orientation )
                {
                    case ConnectorOrientation.Left:
                        endPoint = new Point( sink.Position.X - PathMargin, sink.Position.Y );
                        break;
                    case ConnectorOrientation.Top:
                        endPoint = new Point( sink.Position.X, sink.Position.Y - PathMargin );
                        break;
                    case ConnectorOrientation.Right:
                        endPoint = new Point( sink.Position.X + PathMargin, sink.Position.Y );
                        break;
                    case ConnectorOrientation.Bottom:
                        endPoint = new Point( sink.Position.X, sink.Position.Y + PathMargin );
                        break;
                    default:
                        break;
                }
                linePoints.Insert( 0, startPoint );
                linePoints.Add( endPoint );
            }
            else
            {
                linePoints.Insert( 0, source.Position );
                linePoints.Add( sink.Position );
            }
        }
        private static Rect GetRectWithMargin( ConnectorModel connectorThumb, double margin )
        {
            var rect = connectorThumb.OwnerItem.GetBoundingRectangle();

            rect.Inflate( margin, margin );

            return rect;
        }
        private static Point GetNearestVisibleNeighborSink( Point currentPoint, Point endPoint, ConnectorModel sink, Rect rectSource, Rect rectSink )
        {
            Point s1, s2; // neighbors on sink side
            GetNeighborCorners( sink.Orientation, rectSink, out s1, out s2 );

            bool flag1 = IsPointVisible( currentPoint, s1, new Rect[] { rectSource, rectSink } );
            bool flag2 = IsPointVisible( currentPoint, s2, new Rect[] { rectSource, rectSink } );

            if ( flag1 ) // s1 visible
            {
                if ( flag2 ) // s1 and s2 visible
                {
                    if ( rectSink.Contains( s1 ) )
                    {
                        return s2;
                    }

                    if ( rectSink.Contains( s2 ) )
                    {
                        return s1;
                    }

                    if ( (Distance( s1, endPoint ) <= Distance( s2, endPoint )) )
                    {
                        return s1;
                    }
                    else
                    {
                        return s2;
                    }
                }
                else
                {
                    return s1;
                }
            }
            else // s1 not visible
            {
                if ( flag2 ) // only s2 visible
                {
                    return s2;
                }
                else // s1 and s2 not visible
                {
                    return new Point( double.NaN, double.NaN );
                }
            }
        }
        private static Point GetNearestNeighborSource( ConnectorModel source, Point endPoint, Rect rectSource, out bool flag )
        {
            Point n1, n2; // neighbors
            GetNeighborCorners( source.Orientation, rectSource, out n1, out n2 );

            if ( (Distance( n1, endPoint ) <= Distance( n2, endPoint )) )
            {
                flag = true;
                return n1;
            }
            else
            {
                flag = false;
                return n2;
            }
        }
        internal static List<Point> GetConnectionLine( ConnectorModel source, Point sinkPoint, ConnectorOrientation preferredOrientation )
        {
            List<Point> linePoints = new List<Point>();
            Rect rectSource = GetRectWithMargin( source, ConnectorMargin / 2 );
            Point startPoint = GetOffsetPoint( source, rectSource );
            Point endPoint = sinkPoint;

            linePoints.Add( startPoint );
            Point currentPoint = startPoint;

            if ( !rectSource.Contains( endPoint ) )
            {
                while ( true )
                {
                    if ( IsPointVisible( currentPoint, endPoint, new Rect[] { rectSource } ) )
                    {
                        linePoints.Add( endPoint );
                        break;
                    }

                    bool sideFlag;
                    Point n = GetNearestNeighborSource( source, endPoint, rectSource, out sideFlag );
                    linePoints.Add( n );
                    currentPoint = n;

                    if ( IsPointVisible( currentPoint, endPoint, new Rect[] { rectSource } ) )
                    {
                        linePoints.Add( endPoint );
                        break;
                    }
                    else
                    {
                        Point n1, n2;
                        GetOppositeCorners( source.Orientation, rectSource, out n1, out n2 );
                        if ( sideFlag )
                            linePoints.Add( n1 );
                        else
                            linePoints.Add( n2 );

                        linePoints.Add( endPoint );
                        break;
                    }
                }
            }
            else
            {
                linePoints.Add( endPoint );
            }

            if ( preferredOrientation != ConnectorOrientation.None )
                linePoints = OptimizeLinePoints( linePoints, new Rect[] { rectSource }, source.Orientation, preferredOrientation );
            else
                linePoints = OptimizeLinePoints( linePoints, new Rect[] { rectSource }, source.Orientation, GetOpositeOrientation( source.Orientation ) );

            return linePoints;
        }
        internal static List<Point> GetConnectionLine( ConnectorModel source, ConnectorModel sink, bool showLastLine )
        {
            List<Point> linePoints = new List<Point>();

            Rect rectSource = GetRectWithMargin( source, ConnectorMargin );
            Rect rectSink = GetRectWithMargin( sink, ConnectorMargin );

            Point startPoint = GetOffsetPoint( source, rectSource );
            Point endPoint = GetOffsetPoint( sink, rectSink );

            linePoints.Add( startPoint );
            Point currentPoint = startPoint;

            if ( !rectSink.Contains( currentPoint ) && !rectSource.Contains( endPoint ) )
            {
                while ( true )
                {
                    if ( IsPointVisible( currentPoint, endPoint, new Rect[] { rectSource, rectSink } ) )
                    {
                        linePoints.Add( endPoint );
                        currentPoint = endPoint;
                        break;
                    }

                    Point neighbour = GetNearestVisibleNeighborSink( currentPoint, endPoint, sink, rectSource, rectSink );
                    if ( !double.IsNaN( neighbour.X ) )
                    {
                        linePoints.Add( neighbour );
                        linePoints.Add( endPoint );
                        currentPoint = endPoint;
                        break;
                    }

                    if ( currentPoint == startPoint )
                    {
                        bool flag;
                        Point n = GetNearestNeighborSource( source, endPoint, rectSource, rectSink, out flag );
                        linePoints.Add( n );
                        currentPoint = n;

                        if ( !IsRectVisible( currentPoint, rectSink, new Rect[] { rectSource } ) )
                        {
                            Point n1, n2;
                            GetOppositeCorners( source.Orientation, rectSource, out n1, out n2 );
                            if ( flag )
                            {
                                linePoints.Add( n1 );
                                currentPoint = n1;
                            }
                            else
                            {
                                linePoints.Add( n2 );
                                currentPoint = n2;
                            }
                            if ( !IsRectVisible( currentPoint, rectSink, new Rect[] { rectSource } ) )
                            {
                                if ( flag )
                                {
                                    linePoints.Add( n2 );
                                    currentPoint = n2;
                                }
                                else
                                {
                                    linePoints.Add( n1 );
                                    currentPoint = n1;
                                }
                            }
                        }
                    }
                    else // from here on we jump to the sink node
                    {
                        Point n1, n2; // neighbour corner
                        Point s1, s2; // opposite corner
                        GetNeighborCorners( sink.Orientation, rectSink, out s1, out s2 );
                        GetOppositeCorners( sink.Orientation, rectSink, out n1, out n2 );

                        bool n1Visible = IsPointVisible( currentPoint, n1, new Rect[] { rectSource, rectSink } );
                        bool n2Visible = IsPointVisible( currentPoint, n2, new Rect[] { rectSource, rectSink } );

                        if ( n1Visible && n2Visible )
                        {
                            if ( rectSource.Contains( n1 ) )
                            {
                                linePoints.Add( n2 );
                                if ( rectSource.Contains( s2 ) )
                                {
                                    linePoints.Add( n1 );
                                    linePoints.Add( s1 );
                                }
                                else
                                    linePoints.Add( s2 );

                                linePoints.Add( endPoint );
                                currentPoint = endPoint;
                                break;
                            }

                            if ( rectSource.Contains( n2 ) )
                            {
                                linePoints.Add( n1 );
                                if ( rectSource.Contains( s1 ) )
                                {
                                    linePoints.Add( n2 );
                                    linePoints.Add( s2 );
                                }
                                else
                                    linePoints.Add( s1 );

                                linePoints.Add( endPoint );
                                currentPoint = endPoint;
                                break;
                            }

                            if ( (Distance( n1, endPoint ) <= Distance( n2, endPoint )) )
                            {
                                linePoints.Add( n1 );
                                if ( rectSource.Contains( s1 ) )
                                {
                                    linePoints.Add( n2 );
                                    linePoints.Add( s2 );
                                }
                                else
                                    linePoints.Add( s1 );
                                linePoints.Add( endPoint );
                                currentPoint = endPoint;
                                break;
                            }
                            else
                            {
                                linePoints.Add( n2 );
                                if ( rectSource.Contains( s2 ) )
                                {
                                    linePoints.Add( n1 );
                                    linePoints.Add( s1 );
                                }
                                else
                                    linePoints.Add( s2 );
                                linePoints.Add( endPoint );
                                currentPoint = endPoint;
                                break;
                            }
                        }
                        else if ( n1Visible )
                        {
                            linePoints.Add( n1 );
                            if ( rectSource.Contains( s1 ) )
                            {
                                linePoints.Add( n2 );
                                linePoints.Add( s2 );
                            }
                            else
                                linePoints.Add( s1 );
                            linePoints.Add( endPoint );
                            currentPoint = endPoint;
                            break;
                        }
                        else
                        {
                            linePoints.Add( n2 );
                            if ( rectSource.Contains( s2 ) )
                            {
                                linePoints.Add( n1 );
                                linePoints.Add( s1 );
                            }
                            else
                                linePoints.Add( s2 );
                            linePoints.Add( endPoint );
                            currentPoint = endPoint;
                            break;
                        }
                    }
                }
            }
            else
            {
                linePoints.Add( endPoint );
            }

            linePoints = OptimizeLinePoints( linePoints, new Rect[] { rectSource, rectSink }, source.Orientation, sink.Orientation );

            CheckPathEnd( source, sink, showLastLine, linePoints );
            return linePoints;
        }