Beispiel #1
0
        public bool IntersectsAnyPU(MathCore.LineSegment segment, params AbstractProcessUnit[] exclusionList)
        {
            foreach (UIElement uie in Children)
            {
                ProcessUnitControl puc = uie as ProcessUnitControl;
                if (null == puc)
                {
                    // Not a process unit control
                    continue;
                }

                if (null != exclusionList)
                {
                    bool goNext = false;
                    foreach (AbstractProcessUnit excludeMe in exclusionList)
                    {
                        // See if we want to exclude this one
                        if (object.ReferenceEquals(puc.ProcessUnit, excludeMe))
                        {
                            goNext = true;
                            break;
                        }
                    }

                    if (goNext)
                    {
                        continue;
                    }
                }

                // Build a rectangle for the control
                Point pt = new Point(
                    (double)puc.GetValue(Canvas.LeftProperty),
                    (double)puc.GetValue(Canvas.TopProperty));
                MathCore.Rectangle r;
                if (double.IsNaN(puc.Width) || double.IsNaN(puc.Height) ||
                    0.0 == puc.Width || 0.0 == puc.Height)
                {
                    // Silverlight UI stuff can be funky so we have a condition to use
                    // hard coded dimensions as opposed to getting them from the control
                    r = MathCore.Rectangle.CreateFromCanvasRect(pt, 40.0, 40.0);
                }
                else
                {
                    r = MathCore.Rectangle.CreateFromCanvasRect(pt, puc.Width, puc.Height);
                }

                if (r.GetIntersections(segment).Length > 0)
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #2
0
        public double GetShortestDistanceFromLines(MathCore.Vector location)
        {
            if (0 == m_lines.Count)
            {
                // If there are no lines we'll say it's very far away
                return(double.MaxValue);
            }

            double d = double.MaxValue;

            foreach (Line line in m_lines)
            {
                MathCore.LineSegment ls = new MathCore.LineSegment(
                    line.X1, line.Y1, line.X2, line.Y2);
                double tempD = ls.GetDistance(location);
                if (tempD < d)
                {
                    d = tempD;
                }
            }

            return(d);
        }
Beispiel #3
0
        /// <summary>
        /// Computes line segments for the stream lines that should be rendered. The first point (A)
        /// in the first segment will be the source location and the last point (B) in the last
        /// segment will be the destination location. The number of lines in the array can be any
        /// value greater than 1.
        /// </summary>
        private MathCore.LineSegment[] ComputeLineSegments(out MathCore.Vector midpoint,
                                                           out MathCore.Vector sourceIconLocation)
        {
            MathCore.Vector s = (null == m_stream.Source) ?
                                m_stream.SourceLocation : m_stream.Source.Location;
            MathCore.Vector d = (null == m_stream.Destination) ?
                                m_stream.DestinationLocation : m_stream.Destination.Location;

            // Set the default source icon location. Will get changed below if need be
            sourceIconLocation = s;

            // Start with the simplest case of 1 straight line
            MathCore.LineSegment simplest = new MathCore.LineSegment(
                m_stream.SourceLocation, m_stream.DestinationLocation);

            // If it doesn't intersect any other process units then we'll use it
            if (!m_canvas.IntersectsAnyPU(simplest, m_stream.Source, m_stream.Destination))
            {
                midpoint       = (s + d) / 2.0;
                m_lastMidPoint = midpoint;
                if (null != m_stream.Source)
                {
                    sourceIconLocation = s + (MathCore.Vector.Normalize(d - s) * 30.0);
                }
                return(new MathCore.LineSegment[] { simplest });
            }

            // If that doesn't work, try two lines that make a 90 degree angle
            MathCore.Vector      corner = new MathCore.Vector(s.X, d.Y);
            MathCore.LineSegment a      = new MathCore.LineSegment(s, corner);
            MathCore.LineSegment b      = new MathCore.LineSegment(corner, d);
            if (!m_canvas.IntersectsAnyPU(a, m_stream.Source, m_stream.Destination) &&
                !m_canvas.IntersectsAnyPU(b, m_stream.Source, m_stream.Destination))
            {
                // These lines will work
                midpoint       = corner;
                m_lastMidPoint = midpoint;
                if (null != m_stream.Source)
                {
                    sourceIconLocation = s + (MathCore.Vector.Normalize(a.Direction) * 30.0);
                }
                return(new MathCore.LineSegment[] { a, b });
            }
            // Try the other variant
            corner = new MathCore.Vector(d.X, s.Y);
            a      = new MathCore.LineSegment(s, corner);
            b      = new MathCore.LineSegment(corner, d);
            if (!m_canvas.IntersectsAnyPU(a, m_stream.Source, m_stream.Destination) &&
                !m_canvas.IntersectsAnyPU(b, m_stream.Source, m_stream.Destination))
            {
                // These lines will work
                midpoint       = corner;
                m_lastMidPoint = midpoint;
                if (null != m_stream.Source)
                {
                    sourceIconLocation = s + (MathCore.Vector.Normalize(a.Direction) * 30.0);
                }
                return(new MathCore.LineSegment[] { a, b });
            }

            // If we still don't have it then try a 3-line box
            double dx = Math.Abs(s.X - d.X);
            double dy = Math.Abs(s.Y - d.Y);

            if (dy > dx)
            {
                double xPos = Math.Min(s.X, d.X - 35.0);
                corner = new MathCore.Vector(xPos, s.Y);
                MathCore.Vector corner2 = new MathCore.Vector(xPos, d.Y);
                a = new MathCore.LineSegment(s, corner);
                b = new MathCore.LineSegment(corner, corner2);
                MathCore.LineSegment c = new MathCore.LineSegment(corner2, d);

                if (!m_canvas.IntersectsAnyPU(a, m_stream.Source, m_stream.Destination) &&
                    !m_canvas.IntersectsAnyPU(b, m_stream.Source, m_stream.Destination) &&
                    !m_canvas.IntersectsAnyPU(c, m_stream.Source, m_stream.Destination))
                {
                    // These lines will work
                    midpoint       = (corner + corner2) / 2.0;
                    m_lastMidPoint = midpoint;
                    if (null != m_stream.Source)
                    {
                        sourceIconLocation = s + (MathCore.Vector.Normalize(a.Direction) * 30.0);
                    }
                    return(new MathCore.LineSegment[] { a, b, c });
                }
            }
            else
            {
                double yPos = Math.Min(s.Y, d.Y) - 35.0;
                corner = new MathCore.Vector(s.X, yPos);
                MathCore.Vector corner2 = new MathCore.Vector(d.X, yPos);
                a = new MathCore.LineSegment(s, corner);
                b = new MathCore.LineSegment(corner, corner2);
                MathCore.LineSegment c = new MathCore.LineSegment(corner2, d);

                if (!m_canvas.IntersectsAnyPU(a, m_stream.Source, m_stream.Destination) &&
                    !m_canvas.IntersectsAnyPU(b, m_stream.Source, m_stream.Destination) &&
                    !m_canvas.IntersectsAnyPU(c, m_stream.Source, m_stream.Destination))
                {
                    // These lines will work
                    midpoint       = (corner + corner2) / 2.0;
                    m_lastMidPoint = midpoint;
                    if (null != m_stream.Source)
                    {
                        sourceIconLocation = s + (MathCore.Vector.Normalize(a.Direction) * 30.0);
                    }
                    return(new MathCore.LineSegment[] { a, b, c });
                }
            }

            // Out of options if we come here, so use the straight line
            midpoint       = (s + d) / 2.0;
            m_lastMidPoint = midpoint;
            if (null != m_stream.Source)
            {
                sourceIconLocation = s + (MathCore.Vector.Normalize(d - s) * 30.0);
            }
            return(new MathCore.LineSegment[] { simplest });
        }
Beispiel #4
0
        /// <summary>
        /// Recomputes location of all relevant controls within the stream (endpoint icons,
        /// stream lines, etc.)
        /// </summary>
        public virtual void UpdateStreamLocation()
        {
            // Error check: we shouldn't be here if the control has been removed from the canvas
            if (m_hasBeenRemoved)
            {
                throw new InvalidOperationException(
                          "Stream control that was removed from the PFD is being notified to update its location.");
            }

            if (m_updatingLocation)
            {
                return;
            }
            m_updatingLocation = true;

            MathCore.Vector sPt          = m_stream.SourceLocation;
            MathCore.Vector dPt          = m_stream.DestinationLocation;
            MathCore.Vector lineMidpoint = (sPt + dPt) / 2.0;

            // Compute the line segments for our stream lines
            MathCore.Vector        mid, sIconPt;
            MathCore.LineSegment[] lines = ComputeLineSegments(out mid, out sIconPt);
            // Get the list of UI lines to the right size
            while (m_lines.Count > lines.Length)
            {
                int index = m_lines.Count - 1;
                m_canvas.RemoveChild(m_lines[index]);
                m_lines.RemoveAt(index);
            }
            while (m_lines.Count < lines.Length)
            {
                Line line = new Line();
                m_lines.Add(line);
                m_canvas.AddNewChild(line);

                // Make sure the line has a low z-index
                line.SetValue(Canvas.ZIndexProperty, -1);

                // Remember to set the line color
                Brush b = m_isSelected ? s_streamLineSelected : m_streamLineNotSelected;
                line.Fill   = b;
                line.Stroke = b;
            }
            // Set the positions
            for (int i = 0; i < lines.Length; i++)
            {
                SetLineLocation(m_lines[i], lines[i].A, lines[i].B);
            }

            // Now do the table line if necessary
            if (null != m_table && !m_tableMinimized)
            {
                TableLine.X1 = mid.X;
                TableLine.Y1 = mid.Y;
                TableLine.X2 = m_table.Location.X;
                TableLine.Y2 = m_table.Location.Y;
            }

            // Check if we're minimized then we need to position the mini table
            if (m_tableMinimized)
            {
                m_miniTable.SetValue(Canvas.LeftProperty, mid.X);
                m_miniTable.SetValue(Canvas.TopProperty, mid.Y);
            }

            // Take care of the source drag icon
            if (null != m_stream.Source)
            {
                m_sourceDragIcon.Visibility = System.Windows.Visibility.Collapsed;
                // We need to show the square drag handle and position it
                if (null == m_square)
                {
                    m_square = new System.Windows.Shapes.Rectangle()
                    {
                        Fill   = m_streamLineNotSelected,
                        Width  = 10.0,
                        Height = 10.0
                    };
                    m_canvas.AddNewChild(m_square);
                    m_square.MouseLeftButtonDown += new MouseButtonEventHandler(SourceSquare_MouseLeftButtonDown);
                }
                m_square.Visibility = System.Windows.Visibility.Visible;
                m_square.SetValue(Canvas.LeftProperty, sIconPt.X - 5.0);
                m_square.SetValue(Canvas.TopProperty, sIconPt.Y - 5.0);
            }
            else
            {
                m_sourceDragIcon.Location = new Point(
                    m_stream.SourceLocation.X, m_stream.SourceLocation.Y);
                m_sourceDragIcon.Visibility = System.Windows.Visibility.Visible;
                if (null != m_square)
                {
                    m_square.Visibility = System.Windows.Visibility.Collapsed;
                }
            }

            // Take care of the destination drag icon as well
            if (null == m_stream.Destination)
            {
                m_dstDragIcon.Location   = new Point(dPt.X, dPt.Y);
                m_dstDragIcon.Visibility = System.Windows.Visibility.Visible;
            }
            else
            {
                m_dstDragIcon.Visibility = System.Windows.Visibility.Collapsed;
            }

            // If we have a non-null destination, update the arrow
            if (null != m_stream.Destination)
            {
                // Where the last line segment intersects the destination process unit is where
                // the tip of the arrow is
                Point pt = new Point(
                    m_stream.Destination.Location.X - 20.0,
                    m_stream.Destination.Location.Y - 20.0);
                MathCore.Rectangle   destRect = MathCore.Rectangle.CreateFromCanvasRect(pt, 40.0, 40.0);
                MathCore.Vector[]    isects   = destRect.GetIntersections(lines[lines.Length - 1]);
                MathCore.LineSegment lastLine = lines[lines.Length - 1];

                if (0 == isects.Length)
                {
                    // No clue what to do here
                }

                double minDist = double.MaxValue;
                foreach (MathCore.Vector isectPt in isects)
                {
                    double tempDist = (isectPt - lastLine.A).Length;
                    if (tempDist < minDist)
                    {
                        minDist = tempDist;
                    }
                }

                MathCore.Vector dirNorm = MathCore.Vector.Normalize(lastLine.Direction);
                MathCore.Vector tip     = lastLine.A + dirNorm * minDist;
                MathCore.Vector perp1   = MathCore.Vector.Normalize(
                    MathCore.Vector.GetPerpendicular1(lastLine.Direction));
                MathCore.Vector perp2 = MathCore.Vector.Normalize(
                    MathCore.Vector.GetPerpendicular2(lastLine.Direction));
                MathCore.Vector[] pts = new MathCore.Vector[] {
                    tip,
                    tip - (dirNorm * 10.0) + (perp1 * 10.0),
                    tip - (dirNorm * 10.0) + (perp2 * 10.0)
                };

                // Set the vertices
                for (int i = 0; i < 3; i++)
                {
                    m_arrow.Points[i] = new Point(pts[i].X, pts[i].Y);
                }

                m_arrow.Visibility = System.Windows.Visibility.Visible;
            }

            // Lastly, tell the comment sticky notes to update
            foreach (StickyNoteControl sn in m_stickyNotes)
            {
                sn.UpdateLineToParent();
            }

            m_updatingLocation = false;
        }