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 }
///// <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; }