internal static void Refine(
     int topNodeP,
     int bottomNode,
     Site topSiteP,
     Anchor[] anchors,
     LayerArrays layerArraysP,
     ProperLayeredGraph layeredGraph,
     GeometryGraph originalGraph,
     double layerSeparation) {
     RefinerBetweenTwoLayers refiner = new RefinerBetweenTwoLayers(topNodeP,
                                                                   bottomNode, topSiteP, layerArraysP,
                                                                   layeredGraph, originalGraph, anchors,
                                                                   layerSeparation);
     refiner.Refine();
 }
 RefinerBetweenTwoLayers(
         int topNodeP,
         int bottomNodeP,
         Site topSiteP,
         LayerArrays layerArraysP,
         ProperLayeredGraph layeredGraphP, GeometryGraph originalGraphP, Anchor[] anchorsP, double layerSeparation) {
     this.topNode = topNodeP;
     this.bottomNode = bottomNodeP;
     this.topSite = topSiteP;
     this.bottomSite = topSiteP.Next;
     this.currentTopSite = topSiteP;
     this.currentBottomSite = topSiteP.Next;
     this.layerArrays = layerArraysP;
     this.layeredGraph = layeredGraphP;
     this.originalGraph = originalGraphP;
     this.anchors = anchorsP;
     this.layerSeparation = layerSeparation;
 }
        void CreateSelfSplines()
        {
            foreach (var kv in Database.Multiedges)
            {
                this.ProgressStep();

                IntPair ip = kv.Key;
                if (ip.x == ip.y) {
                    Anchor anchor = Database.Anchors[ip.x];
                    double offset = anchor.LeftAnchor;
                    foreach (IntEdge intEdge in kv.Value) {
                        ProgressStep();

                        double dx = settings.NodeSeparation + settings.MinNodeWidth + offset;
                        double dy = anchor.BottomAnchor / 2;
                        Point p0 = anchor.Origin;
                        Point p1 = p0 + new Point(0, dy);
                        Point p2 = p0 + new Point(dx, dy);
                        Point p3 = p0 + new Point(dx, -dy);
                        Point p4 = p0 + new Point(0, -dy);

                        var s = new Site(p0);
                        var polyline = new SmoothedPolyline(s);
                        s = new Site(s, p1);
                        s = new Site(s, p2);
                        s = new Site(s, p3);
                        s = new Site(s, p4);
                        new Site(s, p0);

                        Curve c;
                        intEdge.Curve = c = polyline.CreateCurve();
                        intEdge.Edge.UnderlyingPolyline = polyline;
                        offset = dx;
                        if (intEdge.Edge.Label != null) {
                            offset += intEdge.Edge.Label.Width;
                            Point center =
                                intEdge.Edge.Label.Center =
                                new Point(c[(c.ParStart + c.ParEnd) / 2].X + intEdge.LabelWidth / 2, anchor.Y);
                            var del = new Point(intEdge.Edge.Label.Width / 2, intEdge.Edge.Label.Height / 2);

                            var box = new Rectangle(center + del, center - del);
                            intEdge.Edge.Label.BoundingBox = box;
                        }
                        Arrowheads.TrimSplineAndCalculateArrowheads(intEdge.Edge.EdgeGeometry,
                                                               intEdge.Edge.Source.BoundaryCurve,
                                                               intEdge.Edge.Target.BoundaryCurve, c, false, 
                                                               settings.EdgeRoutingSettings.KeepOriginalSpline);
                    }
                }
            }
        }
        internal static SmoothedPolyline CreateUnderlyingPolylineForSelfEdge(Point p0, double dx, double dy)
        {
            var p1 = p0 + new Point(0, dy);
            var p2 = p0 + new Point(dx, dy);
            var p3 = p0 + new Point(dx, -dy);
            var p4 = p0 + new Point(0, -dy);

            var site = new Site(p0);
            var polyline = new SmoothedPolyline(site);
            site = new Site(site, p1);
            site = new Site(site, p2);
            site = new Site(site, p3);
            site = new Site(site, p4);
            new Site(site, p0);
            return polyline;
        }
        bool TryToRemoveInflectionEdge(ref Site s) {
            if (!obstacleCalculator.ObstaclesIntersectLine(s.Previous.Point, s.Next.Point)) {
                Site a = s.Previous; //forget s
                Site b = s.Next;
                a.Next = b;
                b.Previous = a;
                s = a;
                return true;
            }
            if (!obstacleCalculator.ObstaclesIntersectLine(s.Previous.Point, s.Next.Next.Point)) {
                //forget about s and s.Next
                Site a = s.Previous;
                Site b = s.Next.Next;
                a.Next = b;
                b.Previous = a;
                s = a;
                return true;
            }
            if (!obstacleCalculator.ObstaclesIntersectLine(s.Point, s.Next.Next.Point)) {
                //forget about s.Next
                Site b = s.Next.Next;
                s.Next = b;
                b.Previous = s;
                return true;
            }

            return false;
        }
 public void InsertPolylineCorner(Point point,Site previousCorner) {
     geomGraphEditor.InsertSite(SelectedEdge.Edge.GeometryEdge,point,previousCorner,SelectedEdge);
     viewer.Invalidate(SelectedEdge);
 }
 private void CreateFilletCurve(Curve curve, ref Site a, ref Site b, ref Site c) {
     do {
         AddSmoothedCorner(a, b, c, curve);
         a = b;
         b = c;
         if (b.Next != null)
             c = b.Next;
         else
             break;
     } while (true);
 }
 private void RefineBeetweenNeighborLayers(Site topSite, int topNode, int bottomNode) {
     RefinerBetweenTwoLayers.Refine(topNode, bottomNode, topSite, this.anchors,
                                    this.layerArrays, this.layeredGraph, this.originalGraph, this.settings.LayerSeparation);
 }
 public UndoRedoAction PrepareForPolylineCornerRemoval(IViewerObject affectedEdge, Site site) {
     var action = new SiteRemoveUndoAction(EditedEdge) {
         RemovedSite = site,
     };
     action.AddAffectedObject(affectedEdge);
     return InsertToListAndSetTheBoxBefore(action);
 }
        /// <summary>
        ///     preparing for an edge corner dragging
        /// </summary>
        /// <param name="geometryEdge"></param>
        /// <param name="site"></param>
        /// <returns></returns>
        public UndoRedoAction PrepareForEdgeCornerDragging(GeomEdge geometryEdge, Site site) {
            EditedEdge = geometryEdge;
            UndoRedoAction edgeDragUndoRedoAction = CreateEdgeEditUndoRedoAction();
//            var edgeRestoreDate = (EdgeRestoreData) edgeDragUndoRedoAction.GetRestoreData(geometryEdge);
//            edgeRestoreDate.Site = site;
            return InsertToListAndSetTheBoxBefore(edgeDragUndoRedoAction);
        }
 /// <summary>
 /// </summary>
 /// <param name="delta">delta of the drag</param>
 /// <param name="e">the modified edge</param>
 /// <param name="site"></param>
 internal static void DragEdgeWithSite(Point delta, GeomEdge e, Site site) {
     e.RaiseLayoutChangeEvent(delta);
     site.Point += delta;
     CreateCurveOnChangedPolyline(e);
 }
 private static void CalculateCoefficiensUnderSite(Site site, double radius){
     double l = radius/(site.Point - site.Previous.Point).Length;
     l = Math.Min(0.5, l);
     site.PreviousBezierSegmentFitCoefficient = l;
     l = radius / (site.Next.Point-site.Point).Length;
     l = Math.Min(0.5, l);
     site.NextBezierSegmentFitCoefficient = l;
 }
 void CacheCorner(Site a, Site b, Site c) {
     cornerTable[new Corner(a.Point,b.Point,c.Point)]=new Tuple<double, double>(b.PreviousBezierSegmentFitCoefficient,b.NextBezierSegmentFitCoefficient);
 }
 bool FindCachedCorner(Site a, Site b, Site c, out double prev, out double next) {
     Corner corner=new Corner(a.Point,b.Point,c.Point);
     Tuple<double, double> prevNext;
     if (cornerTable.TryGetValue(corner, out prevNext)) {
         if (a.Point == corner.a) {
             prev = prevNext.Item1;
             next = prevNext.Item2;
         }
         else {
             prev = prevNext.Item2;
             next = prevNext.Item1;
         }
         foundCachedCorners++;
         return true;
     }
     prev = next = 0;
     return false;
 }
        Site SmoothOneCorner(Site a, Site c, Site b) {
            if (CacheCorners) {
                double p, n;
                if (FindCachedCorner(a, b, c, out p, out n)) {
                    b.PreviousBezierSegmentFitCoefficient = p;
                    b.NextBezierSegmentFitCoefficient = n;
                    return b;
                }
            }
            const double mult = 1.5;
            const double kMin = 0.01;
            
            double k = 0.5;
            CubicBezierSegment seg;
            double u, v;
            if (a.Previous == null) {
                //this will allow to the segment to start from site "a"
                u = 2;
                v = 1;
            } else if (c.Next == null) {
                u = 1;
                v = 2; //this will allow to the segment to end at site "c"
            } else
                u = v = 1;

            do {
                seg = Curve.CreateBezierSeg(k*u, k*v, a, b, c);
                b.PreviousBezierSegmentFitCoefficient = k*u;
                b.NextBezierSegmentFitCoefficient = k*v;
                k /= mult;
            } while (ObstacleCalculator.ObstaclesIntersectICurve(seg) && k > kMin);

            k *= mult; //that was the last k
            if (k < 0.5 && k > kMin) {
                //one time try a smoother seg
                k = 0.5*(k + k*mult);
                seg = Curve.CreateBezierSeg(k*u, k*v, a, b, c);
                if (!ObstacleCalculator.ObstaclesIntersectICurve(seg)) {
                    b.PreviousBezierSegmentFitCoefficient = k*u;
                    b.NextBezierSegmentFitCoefficient = k*v;
                }
            }
            if (CacheCorners)
                CacheCorner(a, b, c);
            return b;
        }
 static bool SegIntersectsBound(Site a, Site b, ParallelogramNode hierarchy) {
     return CurveIntersectsHierarchy(new LineSegment(a.Point, b.Point), hierarchy);
 }
 static bool Flat(Site i) {
     return Point.GetTriangleOrientation(i.Previous.Point, i.Point, i.Next.Point) == TriangleOrientation.Collinear;
 }
 /// <summary>
 ///     prepare for polyline corner insertion
 /// </summary>
 /// <param name="affectedObj">edited objects</param>
 /// <param name="site">the site to insert</param>
 /// <returns></returns>
 internal UndoRedoAction PrepareForPolylineCornerInsertion(IViewerObject affectedObj, Site site) {
     var action = new SiteInsertUndoAction(EditedEdge) {
         InsertedSite = site,
     };
     action.AddAffectedObject(affectedObj);
     return InsertToListAndSetTheBoxBefore(action);
 }
 private void CreateInitialListOfSites() {
     Site currentSite = this.headSite = new Site(EdgePathPoint(0));
     for (int i = 1; i <= edgePath.Count; i++)
         currentSite = new Site(currentSite, EdgePathPoint(i));
 }
 static bool BetweenSites(Site prevSite, Site nextSite, Point point) {
     double par = Point.ClosestParameterOnLineSegment(point, prevSite.Point, nextSite.Point);
     return par > 0.1 && par < 0.9;
 }
        private void AddSmoothedCorner(Site a, Site b, Site c, Curve curve) {
            double k = 0.5;
            CubicBezierSegment seg;
            do {
                seg = Curve.CreateBezierSeg(k, k, a, b, c);
                //if (Routing.db)
                //    LayoutAlgorithmSettings .Show(seg, CreatePolyTest());
                b.PreviousBezierSegmentFitCoefficient = k;
                k /= 2;
            } while (BezierSegIntersectsBoundary(seg));

            k *= 2; //that was the last k
            if (k < 0.5) {//one time try a smoother seg
                k = 0.5 * (k + k * 2);
                CubicBezierSegment nseg = Curve.CreateBezierSeg(k, k, a, b, c);
                if (!BezierSegIntersectsBoundary(nseg)) {
                    b.PreviousBezierSegmentFitCoefficient = b.NextBezierSegmentFitCoefficient = k;
                    seg = nseg;
                }
            }

            if (curve.Segments.Count > 0 && !ApproximateComparer.Close(curve.End, seg.Start))
                curve.AddSegment(new LineSegment(curve.End, seg.Start));
            curve.AddSegment(seg);
        }
        /// <summary>
        ///     insert a polyline corner
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="point">the point to insert the corner</param>
        /// <param name="siteBeforeInsertion"></param>
        /// <param name="affectedEntity">an object to be stored in the undo action</param>
        public void InsertSite(GeomEdge edge, Point point, Site siteBeforeInsertion, IViewerObject affectedEntity) {
            EditedEdge = edge;
            //creating the new site
            Site first = siteBeforeInsertion;
            Site second = first.Next;
            var s = new Site(first, point, second);
            PrepareForPolylineCornerInsertion(affectedEntity, s);

            //just to recalc everything in a correct way
            DragEdgeWithSite(new Point(0, 0), edge, s);
        }
 /// <summary>
 /// delete the polyline corner, shortcut it.
 /// </summary>
 /// <param name="corner"></param>
 public void DeleteCorner(Site corner) {
     geomGraphEditor.DeleteSite(SelectedEdge.Edge.GeometryEdge,corner,SelectedEdge);
     viewer.Invalidate(SelectedEdge);
     viewer.OnDragEnd(new IViewerObject [] { SelectedEdge });
 }
 /// <summary>
 ///     deletes the polyline corner
 /// </summary>
 /// <param name="edge"></param>
 /// <param name="site"></param>
 /// <param name="userData">an object to be stored in the unde action</param>
 public void DeleteSite(GeomEdge edge, Site site, IViewerObject userData) {
     EditedEdge = edge;
     PrepareForPolylineCornerRemoval(userData, site);
     site.Previous.Next = site.Next; //removing the site from the list
     site.Next.Previous = site.Previous;
     //just to recalc everything in a correct way
     DragEdgeWithSite(new Point(0, 0), edge,
         site.Previous);
 }
        private bool CalculateNewTopSite() {
            Point mainSeg = currentBottomSite.Point - currentTopSite.Point;
            double cotan = AbsCotan(mainSeg);
            Point vOfNewSite = new Point();//to silence the compiler
            foreach (Point p in this.topCorners()) {
                double cornerCotan = AbsCotan(p - currentTopSite.Point);
                if (cornerCotan < cotan) {
                    cotan = cornerCotan;
                    vOfNewSite = p;
                }
            }

            if (!ApproximateComparer.Close(cotan, AbsCotan(mainSeg))) {
                currentTopSite = new Site(currentTopSite,
                    FixCorner(currentTopSite.Point, vOfNewSite, currentBottomSite.Point),
                    currentBottomSite
                    );//consider a different FixCorner
                return true;
            }

            return false; //no progress
        }
Example #26
0
        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="source"></param>
        ///// <param name="target"></param>
        ///// <param name="registerForUndo"></param>
        ///// <returns></returns>
        public Drawing.Edge AddEdge(Drawing.Node source, Drawing.Node target, bool registerForUndo)
        {
            Debug.Assert(Graph.FindNode(source.Id) == source);
            Debug.Assert(Graph.FindNode(target.Id) == target);

            Drawing.Edge drawingEdge = Graph.AddEdge(source.Id, target.Id);
            drawingEdge.Label = new Label();
            var geometryEdge = drawingEdge.GeometryEdge = new Microsoft.Msagl.Core.Layout.Edge();
            geometryEdge.GeometryParent = this.Graph.GeometryGraph;

            var a = source.GeometryNode.Center;
            var b = target.GeometryNode.Center;
            if (source == target) {
                Site start = new Site(a);
                Site end = new Site(b);
                var mid1 = source.GeometryNode.Center;
                mid1.X += (source.GeometryNode.BoundingBox.Width / 3 * 2);
                var mid2 = mid1;
                mid1.Y -= source.GeometryNode.BoundingBox.Height / 2;
                mid2.Y += source.GeometryNode.BoundingBox.Height / 2;
                Site mid1s = new Site(mid1);
                Site mid2s = new Site(mid2);
                start.Next = mid1s;
                mid1s.Previous = start;
                mid1s.Next = mid2s;
                mid2s.Previous = mid1s;
                mid2s.Next = end;
                end.Previous = mid2s;
                geometryEdge.UnderlyingPolyline = new SmoothedPolyline(start);
                geometryEdge.Curve = geometryEdge.UnderlyingPolyline.CreateCurve();
            } else {
                Site start = new Site(a);
                Site end = new Site(b);
                Site mids = new Site(a * 0.5 + b * 0.5);
                start.Next = mids;
                mids.Previous = start;
                mids.Next = end;
                end.Previous = mids;
                geometryEdge.UnderlyingPolyline = new SmoothedPolyline(start);
                geometryEdge.Curve = geometryEdge.UnderlyingPolyline.CreateCurve();
            }

            geometryEdge.Source = drawingEdge.SourceNode.GeometryNode;
            geometryEdge.Target = drawingEdge.TargetNode.GeometryNode;
            geometryEdge.EdgeGeometry.TargetArrowhead = new Arrowhead(){Length = drawingEdge.Attr.ArrowheadLength};
            Arrowheads.TrimSplineAndCalculateArrowheads(geometryEdge, geometryEdge.Curve, true,true);

            IViewerEdge ve;
            AddEdge(ve=CreateEdgeWithGivenGeometry(drawingEdge), registerForUndo);
            layoutEditor.AttachLayoutChangeEvent(ve);
            return drawingEdge;
        }
 bool SegIntersectLeftBound(Site a, Site b) {
     return SegIntersectsBound(a, b, rightHierarchy) || SegIntersectsBound(a, b, this.thinRightHierarchy);
 }
        private bool TryToRemoveInflectionEdge(ref Site s) {
            if (s.Next.Next == null)
                return false;
            if (s.Previous == null)
                return false;

            if (s.Turn < 0) {//left turn at s
                if (!SegIntersectRightBound(s, s.Next.Next) && !SegIntersectLeftBound(s, s.Next.Next)) {
                    Site n = s.Next.Next;
                    s.Next = n;                  //forget about s.next
                    n.Previous = s;
                    s = n;
                    return true;
                }

                if (!SegIntersectLeftBound(s.Previous, s.Next) && !SegIntersectRightBound(s.Previous, s.Next)) {
                    Site a = s.Previous; //forget s
                    Site b = s.Next;
                    a.Next = b;
                    b.Previous = a;
                    s = b;
                    return true;
                }
            } else {//right turn at s
                if (!SegIntersectLeftBound(s, s.Next.Next) && !SegIntersectRightBound(s, s.Next.Next)) {
                    Site n = s.Next.Next;
                    s.Next = n;                  //forget about s.next
                    n.Previous = s;
                    s = n;
                    return true;
                }

                if (!SegIntersectRightBound(s.Previous, s.Next) && SegIntersectLeftBound(s.Previous, s.Next)) {
                    Site a = s.Previous; //forget s
                    Site b = s.Next;
                    a.Next = b;
                    b.Previous = a;
                    s = b;
                    return true;
                }
            }
            return false;
        }
 /// <summary>
 /// redoes the editing
 /// </summary>
 public override void Redo() {
     insertedSite = new Site(PrevSite, InsertionPoint, PrevSite.Next);
     insertedSite.NextBezierSegmentFitCoefficient = this.SiteKNext;
     insertedSite.PreviousBezierSegmentFitCoefficient = this.SiteKPrevious;
     GeometryGraphEditor.DragEdgeWithSite(new Point(0, 0), editedEdge, insertedSite);
 }
        /// <summary>
        /// a constructor
        /// </summary>
        /// <param name="previousSite"></param>
        /// <param name="sitePoint"></param>
		public Site(Site previousSite, Point sitePoint )
		{
            ValidateArg.IsNotNull(previousSite, "pr");
            point = sitePoint;
            prev = previousSite;
            previousSite.next = this;
        }