void CreateCurveLine(Metroline line, EdgeGeometry edge) { var c = new Curve(); Point start = FindCurveStart(metroGraphData, metroOrdering, line); Point currentEnd = start; var hubSegsOfLine = HubSegsOfLine(metroGraphData, metroOrdering, line); foreach (var seg in hubSegsOfLine) { if (seg == null) continue; c.AddSegment(new LineSegment(currentEnd, seg.Start)); c.AddSegment(seg); currentEnd = seg.End; } c.AddSegment(new LineSegment(currentEnd, FindCurveEnd(metroGraphData, metroOrdering, line))); edge.Curve = c; if (CreateUnderlyingPolylines) edge.SmoothedPolyline = BuildUnderlyingPolyline(start, currentEnd, hubSegsOfLine); }
/// <summary> /// Create in the specified curve, a rectangle with smoothed corners /// </summary> /// <param name="c"></param> /// <param name="width">the rectangle width</param> /// <param name="height">the rectangle height</param> /// <param name="radiusInXDirection">the length of the x axis of the corner smoothing ellipse</param> /// <param name="radiusInYDirection">the length of the y axis of the corner smoothing ellipse</param> /// <param name="center">the rectangle center</param> /// <returns></returns> static internal void CreateRectangleWithRoundedCorners(Curve c, double width, double height, double radiusInXDirection, double radiusInYDirection, Point center) { if (radiusInXDirection == 0 || radiusInYDirection == 0) { CreateRectangle(c, width, height, center); return; } double w = width / 2; if (radiusInXDirection > w/2) radiusInXDirection = w/2; double h = height / 2; if (radiusInYDirection > h/2) radiusInYDirection = h/2; double x = center.X; double y = center.Y; double ox = w - radiusInXDirection; double oy = h - radiusInYDirection; double top = y + h; double bottom = y - h; double left = x - w; double right = x + w; //ellipse's axises Point a = new Point(radiusInXDirection, 0); Point b = new Point(0, radiusInYDirection); c.IncreaseSegmentCapacity(8); if (ox > 0) c.AddSegment(new LineSegment(new Point(x - ox, bottom), new Point(x + ox, bottom))); c.AddSegment(new Ellipse(1.5 * Math.PI, 2 * Math.PI, a, b, x + ox, y - oy)); if (oy > 0) c.AddSegment(new LineSegment(new Point(right, y - oy), new Point(right, y + oy))); c.AddSegment(new Ellipse(0, 0.5 * Math.PI, a, b, x + ox, y + oy)); if (ox > 0) c.AddSegment(new LineSegment(new Point(x + ox, top), new Point(x - ox, top))); c.AddSegment(new Ellipse(0.5 * Math.PI, Math.PI, a, b, x - ox, y + oy)); if (oy > 0) c.AddSegment(new LineSegment(new Point(left, y + oy), new Point(left, y - oy))); c.AddSegment(new Ellipse(Math.PI, 1.5 * Math.PI, a, b, x - ox, y - oy)); }
ICurve TrimEntryCurve(Tuple<double, double> span) { var start = span.Item1; var end = span.Item2; if (start < end) { return this.EntryCurve.Trim(start, end); } // For the classes that implement it, wrap the Trim. if ((this.EntryCurve is Polyline) || (this.EntryCurve is Curve) || (this.EntryCurve is RoundedRect)) { return this.EntryCurve.TrimWithWrap(start, end); } // Ellipse does not (yet) support TrimWithWrap but for our purposes we can deal with it as a Curve. if (this.EntryCurve is Ellipse) { var c = new Curve(); c.AddSegment(this.EntryCurve.Trim(start, this.EntryCurve.ParEnd)); c.AddSegment(this.EntryCurve.Trim(this.EntryCurve.ParStart, end)); return c; } // For the remaining implementations of ICurve, this is what Trim does if start is greater than end, unless it throws. return this.EntryCurve.Trim(end, start); }
private Curve ReadCurve() { var c = new Curve(); Match m; while ((m = ParseNextOrDone(RectFileStrings.ParseSegment, RectFileStrings.EndCurve)).Success) { c.AddSegment(LoadLineSegment(m)); } return c; }
// static int calls; // bool debug { get { return calls == 5;} } Curve Poly() { Curve c = new Curve(); for (Site s = this.headSite; s.Next != null; s = s.Next) c.AddSegment(new CubicBezierSegment(s.Point, 2 * s.Point / 3 + s.Next.Point / 3, s.Point / 3 + 2 * s.Next.Point / 3, s.Next.Point)); return c; }
void ProceedWithLines(Curve curve, CurveStream curveStream, ref Point currentPoint) { do { curve.AddSegment(new LineSegment(currentPoint, currentPoint = GetNextPointFromCurveData(curveStream))); } while (curveStream.PickNextCurveStreamElement() is DoubleStreamElement); }
/// <summary> /// Routes a self edge inside the given "howMuchToStickOut" parameter /// </summary> /// <param name="boundaryCurve"></param> /// <param name="howMuchToStickOut"></param> /// <returns></returns> static internal ICurve RouteSelfEdgeAtSide(ICurve boundaryCurve, double howMuchToStickOut) { //we just need to find the box of the corresponding node var w = boundaryCurve.BoundingBox.Width; var h = boundaryCurve.BoundingBox.Height; var center = boundaryCurve.BoundingBox.Center; var p0 = new Point(center.X, center.Y - h / 4); var p1 = new Point(center.X - w / 2 - howMuchToStickOut, center.Y - h / 4); var p2 = new Point(center.X - w / 2 - howMuchToStickOut, center.Y); var p3 = new Point(center.X - w / 2 - howMuchToStickOut, center.Y + h / 4); var p4 = new Point(center.X, center.Y + h / 4); var curve = new Curve(); curve.AddSegment(new CubicBezierSegment(p0, p1, p1, p2)); curve.AddSegment(new CubicBezierSegment(p2, p3, p3, p4)); return curve; }
static ICurve CreatObstaceOnLabel(Label label) { var c = new Curve(); double obstacleBottom = label.Center.Y - label.Height/4; c.AddSegment(new LineSegment(new Point(label.BoundingBox.Left, obstacleBottom), new Point(label.BoundingBox.Right, obstacleBottom))); Curve.ContinueWithLineSegment(c, label.BoundingBox.RightTop); Curve.ContinueWithLineSegment(c, label.BoundingBox.LeftTop); Curve.CloseCurve(c); return c; }
static Curve TrimCurve(Curve curve, double u, double v) { Debug.Assert(u >= curve.ParStart && u <= curve.ParEnd); Debug.Assert(v >= curve.ParStart && v <= curve.ParEnd); if (u < v) return curve.Trim(u, v) as Curve; var c = new Curve(); c.AddSegment(curve.Trim(u, curve.ParEnd) as Curve); c.AddSegment(curve.Trim(curve.ParStart, v) as Curve); return c; }
/// <summary> /// Convert points to line curve /// </summary> internal static Curve CreateLineCurve(List<Point> route) { ValidateArg.IsNotNull(route, "route"); var curve = new Curve(route.Count); for (int i = 0; i + 1 < route.Count; i++) curve.AddSegment(new LineSegment(route[i], route[i + 1])); return curve; }
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> ///adds a line segment to the curve ///</summary> ///<param name="curve"></param> ///<param name="pointA"></param> ///<param name="pointB"></param> ///<returns></returns> public static Curve AddLineSegment(Curve curve, Point pointA, Point pointB) { ValidateArg.IsNotNull(curve, "curve"); return curve.AddSegment(new LineSegment(pointA, pointB)); }
/// <summary> /// Returns the trimmed curve, wrapping around the end if start is greater than end. /// </summary> /// <param name="start">The starting parameter</param> /// <param name="end">The ending parameter</param> /// <returns>The trimmed curve</returns> public ICurve TrimWithWrap(double start, double end) { Debug.Assert(start >= ParStart && start <= ParEnd); Debug.Assert(end >= ParStart && end <= ParEnd); if (start < end) return Trim(start, end) as Curve; Debug.Assert(ApproximateComparer.Close(Start, End), "Curve must be closed to wrap"); var c = new Curve(); c.AddSegment(Trim(start, ParEnd) as Curve); c.AddSegment(Trim(ParStart, end) as Curve); return c; }
///// <summary> ///// //sort intersections by the a parameter ///// </summary> ///// <param name="dictionary"></param> ///// <param name="coeff"></param> ///// <param name="side1"></param> //internal static void AddRealIntersectionsToDictionaryForClosedCurve(SortedDictionary<double, IntersectionInfo> dictionary, ICurve coeff, Curve side1) { // StopIntersect si = new StopIntersect((new XExaminer(dictionary, coeff, side1)).IntersectionExaminerForClosedCurveWithIntersectionLifting); // Curve.GetAllIntersections(coeff, side1, si, true); //} //internal static void AddRealIntersectionsWithTreeToDictionaryForClosedCurves(SortedDictionary<double, IntersectionInfo> dictionary, ICurve coeff, ParallelogramNode bound) { // if( Parallelogram.Intersect( coeff.ParallelogramNodeOverICurve.Parallelogram, bound.Parallelogram)){ // ParallelogramBinaryTreeNode treeNode = bound as ParallelogramBinaryTreeNode; // if (treeNode != null) { // AddRealIntersectionsWithTreeToDictionaryForClosedCurves(dictionary, coeff, treeNode.LeftSon); // AddRealIntersectionsWithTreeToDictionaryForClosedCurves(dictionary, coeff, treeNode.RightSon); // } else // AddRealIntersectionsToDictionaryForClosedCurve(dictionary, coeff, (Curve)((ParallelogramNodeOverICurve)bound).Seg); // } //} #region ICurve Members /// <summary> /// clones the curve. /// </summary> /// <returns>the cloned curve</returns> public ICurve Clone() { var c = new Curve(Segments.Count); foreach (ICurve seg in Segments) c.AddSegment(seg.Clone()); return c; }
/// <summary> /// Returns the trim curve /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <returns></returns> public ICurve Trim(double start, double end) { AdjustStartEndEndParametersToDomain(ref start, ref end); int sseg; double spar; GetSegmentAndParameter(start, out spar, out sseg); int eseg; double epar; GetSegmentAndParameter(end, out epar, out eseg); if (sseg == eseg) return Segments[sseg].Trim(spar, epar); var c = new Curve(eseg-sseg+1); if (spar < Segments[sseg].ParEnd) c = c.AddSegment(Segments[sseg].Trim(spar, Segments[sseg].ParEnd)); for (int i = sseg + 1; i < eseg; i++) c = c.AddSegment(Segments[i]); if (Segments[eseg].ParStart < epar) c = c.AddSegment(Segments[eseg].Trim(Segments[eseg].ParStart, epar)); return c; }
/// <summary> /// this[Reverse[t]]=this[ParEnd+ParStart-t] /// </summary> /// <returns></returns> public ICurve Reverse() { var ret = new Curve(segs.Count); for (int i = segs.Count - 1; i >= 0; i--) ret.AddSegment(segs[i].Reverse()); return ret; }
Curve CreateSmoothedPolyline() { RemoveVerticesWithNoTurns(); Curve curve = new Curve(); Site a = headSite;//the corner start Site b; //the corner origin Site c;//the corner other end if (Curve.FindCorner(a, out b, out c)) { CreateFilletCurve(curve, ref a, ref b, ref c); curve = ExtendCurveToEndpoints(curve); } else curve.AddSegment(new LineSegment(EdgePathPoint(0), EdgePathPoint(edgePath.Count))); return curve; }
public void ClosestParameterWithinBounds() { #if GDI_DEBUG_VIEWER if (!MsaglTestBase.DontShowTheDebugViewer()) { DisplayGeometryGraph.SetShowFunctions(); } #endif var ellipse = CurveFactory.CreateEllipse(8, 10, new Point()); var point = new Point(20, 1); var t = ellipse.ClosestParameter(point); var low = t - 1; var high = t + 1; var t1 = ellipse.ClosestParameterWithinBounds(point, low, high); #if GDI_DEBUG_VIEWER if (!MsaglTestBase.DontShowTheDebugViewer()) { LayoutAlgorithmSettings.ShowDebugCurves(new DebugCurve(100, 0.1, "black", ellipse), new DebugCurve(100, 0.01, "brown", new LineSegment(ellipse[t], point)), new DebugCurve(100, 0.01, "green", new LineSegment(ellipse[t1], point))); } #endif var dist = point - ellipse[t]; var dist1 = point - ellipse[t1]; Assert.IsTrue(ApproximateComparer.Close(dist.Length, dist1.Length) && ApproximateComparer.Close(t, t1)); #if GDI_DEBUG_VIEWER if (!MsaglTestBase.DontShowTheDebugViewer()) { LayoutAlgorithmSettings.ShowDebugCurves(new DebugCurve(ellipse), new DebugCurve("red", new LineSegment(point, ellipse[t]))); } #endif var curve = new Curve(); curve.AddSegment(new LineSegment(new Point(-10, -10), new Point(10, -10))); curve.AddSegment(new Ellipse(0, Math.PI / 2, new Point(0, -10), new Point(10, 0), new Point(10, 0))); Curve.ContinueWithLineSegment(curve, new Point(20, 10)); curve.AddSegment(new CubicBezierSegment(curve.End, new Point(20, 20), new Point(15, 25), new Point(10, 25))); Curve.ContinueWithLineSegment(curve, new Point(-10, 25)); Point p = new Point(11, 0); t = curve.ClosestParameter(p); #if GDI_DEBUG_VIEWER if (!MsaglTestBase.DontShowTheDebugViewer()) { LayoutAlgorithmSettings.ShowDebugCurves(new DebugCurve(curve), new DebugCurve("red", new LineSegment(p, curve[t]))); } #endif t1 = curve.ClosestParameterWithinBounds(p, 1 + Math.PI / 4, 2); #if GDI_DEBUG_VIEWER if (!MsaglTestBase.DontShowTheDebugViewer()) { LayoutAlgorithmSettings.ShowDebugCurves(new DebugCurve(curve), new DebugCurve("red", new LineSegment(p, curve[t1]))); } #endif Assert.IsTrue(t1 < t); p = new Point(30, 30); t = curve.ClosestParameter(p); t1 = curve.ClosestParameterWithinBounds(p, t - 0.5, t + 0.5); Assert.IsTrue(t > 1 + Math.PI / 2 + 1 && t < 1 + Math.PI / 2 + 2); Assert.IsTrue(ApproximateComparer.Close(t, t1)); var poly = new Polyline(new Point(0, 0), new Point(10, 0), new Point(20, 10)); p = new Point(9, 9); const double l = 0.7; const double h = 1.3; t = poly.ClosestParameterWithinBounds(p, l, h); #if GDI_DEBUG_VIEWER if (!MsaglTestBase.DontShowTheDebugViewer()) { LayoutAlgorithmSettings.ShowDebugCurves(new DebugCurve(poly), new DebugCurve("red", new LineSegment(p, poly[t]))); } #endif var d = (p - poly[t]).Length; Assert.IsTrue(d <= (p - poly[l]).Length + ApproximateComparer.Tolerance && d < (p - poly[h]).Length + ApproximateComparer.Tolerance && d < (p - poly[(l + h) / 2]).Length + ApproximateComparer.Tolerance); }
private Curve ExtendCurveToEndpoints(Curve curve) { Point p = this.EdgePathPoint(0); if (!ApproximateComparer.Close(p, curve.Start)) { Curve nc = new Curve(); nc.AddSegs(new LineSegment(p, curve.Start), curve); curve = nc; } p = this.EdgePathPoint(edgePath.Count); if (!ApproximateComparer.Close(p, curve.End)) curve.AddSegment(new LineSegment(curve.End, p)); return curve; }
internal static ICurve FitArcsIntoCorners(double radius, Point[] polyline) { IEnumerable<Ellipse> ellipses = GetFittedArcSegs(radius, polyline); var curve = new Curve(polyline.Length); Ellipse prevEllipse = null; foreach (Ellipse ellipse in ellipses) { bool ellipseIsAlmostCurve = EllipseIsAlmostLineSegment(ellipse); if (prevEllipse != null) { if (ellipseIsAlmostCurve) Curve.ContinueWithLineSegment(curve, CornerPoint(ellipse)); else { Curve.ContinueWithLineSegment(curve, ellipse.Start); curve.AddSegment(ellipse); } } else { if (ellipseIsAlmostCurve) Curve.AddLineSegment(curve, polyline[0], CornerPoint(ellipse)); else { Curve.AddLineSegment(curve, polyline[0], ellipse.Start); curve.AddSegment(ellipse); } } prevEllipse = ellipse; } if (curve.Segments.Count > 0) Curve.ContinueWithLineSegment(curve, polyline[polyline.Length - 1]); else Curve.AddLineSegment(curve, polyline[0], polyline[polyline.Length - 1]); return curve; }
/// <summary> /// create a triangle inside the box formed by width and height. /// </summary> /// <param name="width"></param> /// <param name="height"></param> /// <param name="center"></param> /// <returns></returns> static public ICurve CreateInteriorTriangle(double width, double height, Point center) { double w = width / 2; double h = height / 2; double x = center.X; double y = center.Y; Curve c = new Curve(3); Point[] p = new Point[] { new Point(x - w, y - h), new Point(x + w, y - h), new Point(x, y + h) }; c.AddSegment(new LineSegment(p[0], p[1])); c.AddSegment(new LineSegment(p[1], p[2])); c.AddSegment(new LineSegment(p[2], p[0])); return c; }
static void AddBezieSegsToEdgeFromPosData(Edge edge, List<P2> list) { var curve = new Curve(); for (int i = 0; i + 3 < list.Count; i += 3) curve.AddSegment(new CubicBezierSegment(list[i], list[i + 1], list[i + 2], list[i + 3])); InitGeomEdge(edge); edge.GeometryEdge.Curve = curve; }
private ICurve BoundingBoxCurve(ref Rectangle rectangle) { Curve c = new Curve(); c.AddSegment(new LineSegment(rectangle.LeftTop, rectangle.LeftBottom)); Curve.ContinueWithLineSegment(c, rectangle.RightBottom); Curve.ContinueWithLineSegment(c, rectangle.RightTop); Curve.CloseCurve(c); return c; }
void AddCurveSegment(CurveStream curveStream, char c, Curve curve, ref Point currentPoint) { switch (c) { case 'M': //moveto currentPoint = GetNextPointFromCurveData(curveStream); break; case 'm': //relative moveto throw new NotImplementedException(); case 'Z': case 'z': //closepath if (curve.Segments.Count == 0) Error("the curve is too short"); curve.AddSegment(new LineSegment(currentPoint, currentPoint = curve.Start)); break; case 'L': //lineto ProceedWithLines(curve, curveStream, ref currentPoint); break; case 'l': //lineto relative throw new NotImplementedException(); case 'H': //lineto horizontal throw new NotImplementedException(); case 'h': //lineto horizontal relative throw new NotImplementedException(); case 'V': //lineto vertical throw new NotImplementedException(); case 'v': //lineto vertical relative throw new NotImplementedException(); case 'C': //cubic Bezier ProceedWithCubicBeziers(curve, curveStream, ref currentPoint); break; case 'c': //cubic Bezier relative throw new NotImplementedException(); case 'S': //cubic Bezier shorthand throw new NotImplementedException(); case 's': //cubic Bezier relative shorthand throw new NotImplementedException(); case 'Q': //quadratic Bezier throw new NotImplementedException(); case 'q': //quadratic Bezier relative throw new NotImplementedException(); case 'T': //quadratic Bezier shorthand throw new NotImplementedException(); case 't': //quadratic Bezier relative shorthand throw new NotImplementedException(); case 'A': //elleptical arc ReadEllepticalArc(curve, curveStream, ref currentPoint); break; case 'a': //eleptical arc relative throw new NotImplementedException(); default: Error("unknown character " + c); break; } }
void ReadEllepticalArc(Curve curve, CurveStream curveStream, ref Point currentPoint) { curve.AddSegment(ReadEllepticalArc(curveStream, ref currentPoint)); }
internal static Shape CurveFromPoints(Point[] points) { var curve = new Curve(); for (int ii = 0; ii < points.Length - 1; ++ii) { curve.AddSegment(new LineSegment(points[ii], points[ii + 1])); } curve.AddSegment(new LineSegment(points[points.Length - 1], points[0])); return new Shape(curve); }