public void LineTo(float x, float y) { if (m_Segments.Count == 0) { MoveTo(x, y); } var n = m_Segments.Count; var a = m_Segments[n - 1].P0; var b = LocalPoint(x / PixelsPerUnit, y / PixelsPerUnit); var line = VectorUtils.MakeLine(a, b); m_Segments[n - 1] = new BezierPathSegment() { P0 = line.P0, P1 = line.P1, P2 = line.P2 }; m_Segments.Add(new BezierPathSegment() { P0 = line.P3 }); }
public void BezierCurveTo(float cx1, float cy1, float cx2, float cy2, float x, float y) { if (m_Segments.Count == 0) { MoveTo(x, y); } var n = m_Segments.Count; var a = m_Segments[n - 1].P0; var b = LocalPoint(cx1 / PixelsPerUnit, cy1 / PixelsPerUnit); var c = LocalPoint(cx2 / PixelsPerUnit, cy2 / PixelsPerUnit); var d = LocalPoint(x / PixelsPerUnit, y / PixelsPerUnit); m_Segments[n - 1] = new BezierPathSegment() { P0 = a, P1 = b, P2 = c }; m_Segments.Add(new BezierPathSegment() { P0 = d }); }
/// <summary> /// New PolyShape from Unity contour data. /// </summary> /// <param name="contour">Contour data</param> public static PolyShape Create(BezierContour contour) { PolyShape shape = Create(); int vertexCount = contour.Segments.Length; shape.vertices = new Vertex[vertexCount]; for (int i = 0; i < vertexCount; i++) { shape.vertices[i] = new Vertex(); } for (int i = 0; i < vertexCount; i++) { BezierPathSegment segment = contour.Segments[i]; shape.vertices[i].position = segment.P0; shape.vertices[i].exitCP = segment.P1; shape.vertices[shape.NextIndex(i)].enterCP = segment.P2; shape.vertices[i].segmentCurves = true; } shape.closed = contour.Closed; return(shape); }
public bool Intersect(BezierPathSegment b) { CubicBezier cb = b.Bezier; LineSegment l; Vector2[] temp; l = new LineSegment(cb.P0, cb.P1); if (Intersect(l, out temp)) { return(true); } l = new LineSegment(cb.P1, cb.P2); if (Intersect(l, out temp)) { return(true); } l = new LineSegment(cb.P2, cb.P3); if (Intersect(l, out temp)) { return(true); } l = new LineSegment(cb.P3, cb.P0); if (Intersect(l, out temp)) { return(true); } return(false); }
/// <summary> /// walks along the bezier path and creates a straight line segment approximation /// </summary> /// <param name="path"></param> /// <param name="sampleDistance"></param> /// <returns></returns> public PointPath ConvertBezierPathToPointPath(IPath path, double sampleDistance) { PointPath pathOut = new PointPath(); foreach (IPathSegment seg in path) { if (seg is BezierPathSegment == false) { throw new InvalidOperationException(); } BezierPathSegment bseg = seg as BezierPathSegment; PointOnPath p = seg.StartPoint; double refDist = 0; while (refDist == 0) { PointOnPath p2; refDist = sampleDistance; p2 = seg.AdvancePoint(p, ref refDist); pathOut.Add(new LinePathSegment(p.pt, p2.pt)); p = p2; } } return(pathOut); }
/// <summary> /// New PolyShape from Unity shape data. /// </summary> /// <param name="shape">Shape data</param> /// <param name="shapeTransform">Transform matrix</param> public PolyShape(Shape shape, Matrix2D shapeTransform) { int vertexCount = 0; foreach (BezierContour contour in shape.Contours) { vertexCount += contour.Segments.Length; } vertices = new Vertex[vertexCount]; for (int i = 0; i < vertexCount; i++) { vertices[i] = new Vertex(); } foreach (BezierContour contour in shape.Contours) { for (int i = 0; i < contour.Segments.Length; i++) { BezierPathSegment segment = contour.Segments[i]; vertices[i].position = shapeTransform.MultiplyPoint(segment.P0); vertices[i].exitCP = shapeTransform.MultiplyPoint(segment.P1); vertices[NextIndex(i)].enterCP = shapeTransform.MultiplyPoint(segment.P2); vertices[i].segmentCurves = true; } closed = contour.Closed; } if (shape.PathProps.Stroke != null) { colorOutline = shape.PathProps.Stroke.Color; } }
public BezierPathSegment[] ConvertPointsToSegments(BodyPoint[] pts) { float y = -1f; int cnt = pts.Length + (closed ? 1 : 0); BezierPathSegment[] segs = new BezierPathSegment[cnt]; int i = 0; for (int j = 0; j < pts.Length; j++) { BodyPoint point = pts[j]; // Next point... bool last = i >= pts.Length - 1; BodyPoint nextPoint = last ? pts[0] : pts[i + 1]; // Make segment BezierPathSegment s = new BezierPathSegment() { P0 = new Vector2(point.p.x, point.p.y * y), P1 = new Vector2((point.p.x + point.o.x), (point.p.y + point.o.y) * y), P2 = new Vector2((nextPoint.p.x + nextPoint.i.x), (nextPoint.p.y + nextPoint.i.y) * y) }; segs[i] = s; i += 1; } if (pts.Length > 0 && i == cnt - 1) { BezierPathSegment final = new BezierPathSegment() { P0 = new Vector2(pts[0].p.x, pts[0].p.y * y) }; segs[i] = final; } /* READOUT */ //foreach (BezierPathSegment s in segs) //{ // Debug.Log("P0: " + s.P0 + " P1: " + s.P1 + " P2: " + s.P2); //} return(segs); }
private void RenderRelativePath(VehicleState vs, Path transPath, Graphics g, WorldTransform t, bool isArbiterPath) { if ((isArbiterPath && DrawingUtility.DrawArbiterLanePath) || (!isArbiterPath && DrawingUtility.DrawOperationalLanePath)) { // compute the rotation matrix to add in our vehicles rotation /*Matrix3 rotMatrix = new Matrix3( * Math.Cos(vs.heading.ArcTan), -Math.Sin(vs.heading.ArcTan), 0, * Math.Sin(vs.heading.ArcTan), Math.Cos(vs.heading.ArcTan), 0, * 0, 0, 1); * * // compute the translation matrix to move our vehicle's location * Matrix3 transMatrix = new Matrix3( * 1, 0, vs.xyPosition.X, * 0, 1, vs.xyPosition.Y, * 0, 0, 1); * * // compute the combined transformation matrix * Matrix3 m = rotMatrix * transMatrix; * * // clone, transform and add each segment to our path * transPath.Transform(m);*/ float nomPixelWidth = 2.0f; float penWidth = nomPixelWidth / t.Scale; Pen arbiterPen = new Pen(Color.FromArgb(100, DrawingUtility.ArbiterLanePath), penWidth); Pen operationalPen = new Pen(Color.FromArgb(100, DrawingUtility.OperationalLanePath), penWidth); // display path foreach (IPathSegment ps in transPath) { if (ps is BezierPathSegment) { BezierPathSegment seg = (BezierPathSegment)ps; CubicBezier cb = seg.cb; if (isArbiterPath) { g.DrawBezier(arbiterPen, DrawingUtility.ToPointF(cb.P0), DrawingUtility.ToPointF(cb.P1), DrawingUtility.ToPointF(cb.P2), DrawingUtility.ToPointF(cb.P3)); } else { g.DrawBezier(operationalPen, DrawingUtility.ToPointF(cb.P0), DrawingUtility.ToPointF(cb.P1), DrawingUtility.ToPointF(cb.P2), DrawingUtility.ToPointF(cb.P3)); } } } } }
void ApplySVGPath() { string svgPath = "Assets/RouteData/drawsvg.svg"; SVGParser.SceneInfo sceneInfo = SVGParser.ImportSVG(new StreamReader(svgPath)); Shape path = sceneInfo.NodeIDs["e1_polyline"].Shapes[0]; Debug.Log(path); BezierContour[] cs = path.Contours; BezierContour c = cs[0]; //Debug.Log(c); BezierPathSegment[] ss = c.Segments; Debug.Log($"SVGRoute segments count: {ss.Length}"); for (int i = 0; i < ss.Length; i++) { BezierPathSegment s = ss[i]; Debug.Log($"SVGRoute Segment points: {s.P0} -> {s.P1} -> {s.P2}"); var debug1 = GameObject.Find($"SVGTarget{(i * 3) + 1}"); var debug2 = GameObject.Find($"SVGTarget{(i * 3) + 2}"); var debug3 = GameObject.Find($"SVGTarget{(i * 3) + 3}"); debug1.transform.localPosition = s.P0; debug2.transform.localPosition = s.P1; debug3.transform.localPosition = s.P2; Debug.Log(debug3); } // debug1.transform.position = new Vector3(s.P0.x, 0.1f, s.P0.y); // //(s.P0.x / 10) - 10f, 0.1f, (s.P0.y / 10) + 4.3f); // debug2.transform.position = new Vector3(s.P1.x, 0.1f, s.P1.y); // debug3.transform.position = new Vector3(s.P2.x, 0.1f, s.P2.y); var debug0 = GameObject.Find("SVGTarget0"); debug0.transform.localPosition = Vector3.zero; //path. //var fill = shape.Fill as SolidFill; //fill.Color = Color.red; // ... //var geoms = VectorUtils.TessellateScene(sceneInfo.Scene, tessOptions); //var sprite = VectorUtils.BuildSprite(geoms, 100.0f, VectorUtils.Alignment.Center, Vector2.zero, 128, true); }
public Boolean IsEntireBezPathClear(IPath p, List <Polygon> obstacles) { foreach (IPathSegment seg in p) { if (seg is BezierPathSegment == false) { return(false); } BezierPathSegment bseg = seg as BezierPathSegment; if (!IsBezSegmentClear(bseg, obstacles, .2)) { return(false); } } return(true); }
/// <summary> /// New PolyShape from Unity contour data. /// </summary> /// <param name="contour">Contour data</param> public PolyShape(BezierContour contour) { int vertexCount = contour.Segments.Length; vertices = new Vertex[vertexCount]; for (int i = 0; i < vertexCount; i++) { vertices[i] = new Vertex(); } for (int i = 0; i < vertexCount; i++) { BezierPathSegment segment = contour.Segments[i]; vertices[i].position = segment.P0; vertices[i].exitCP = segment.P1; vertices[NextIndex(i)].enterCP = segment.P2; vertices[i].segmentCurves = true; } closed = contour.Closed; }
private Boolean IsBezSegmentClear(BezierPathSegment seg, List <Polygon> obstacles, double advanceDistance) { PointOnPath p = seg.StartPoint; double refDist = 0; while (refDist == 0) { PointOnPath p2; refDist = advanceDistance; p2 = seg.AdvancePoint(p, ref refDist); foreach (Polygon poly in obstacles) { if (poly.ConvexDoesIntersect(p.pt, p2.pt)) { return(false); } } p = p2; } return(true); }
public void PathEndsPerfectlyMatch_ReturnsTrue_WhenEndsPerfectlyMatches() { // Should return false if there's less than 2 segments Assert.IsFalse(VectorUtils.PathEndsPerfectlyMatch(new BezierPathSegment[0])); var path = new BezierPathSegment[] { new BezierPathSegment() { P0 = Vector2.zero, P1 = new Vector2(-10, 10), P2 = new Vector2(10, 10) }, new BezierPathSegment() { P0 = Vector2.zero } }; Assert.IsTrue(VectorUtils.PathEndsPerfectlyMatch(path)); path[1].P0 = Vector2.one; Assert.IsFalse(VectorUtils.PathEndsPerfectlyMatch(path)); }
public void SegmentsInPath_ReturnsAllSegmentsInPath() { var points = new Vector2[7]; for (int i = 0; i < points.Length; ++i) { points[i] = Vector2.one * i; } var path = new BezierPathSegment[] { new BezierPathSegment() { P0 = points[0], P1 = points[1], P2 = points[2] }, new BezierPathSegment() { P0 = points[3], P1 = points[4], P2 = points[5] }, new BezierPathSegment() { P0 = points[6] } }; var segs = VectorUtils.SegmentsInPath(path).ToList(); Assert.AreEqual(2, segs.Count); Assert.AreEqual(points[0], segs[0].P0); Assert.AreEqual(points[1], segs[0].P1); Assert.AreEqual(points[2], segs[0].P2); Assert.AreEqual(points[3], segs[0].P3); Assert.AreEqual(points[3], segs[1].P0); Assert.AreEqual(points[4], segs[1].P1); Assert.AreEqual(points[5], segs[1].P2); Assert.AreEqual(points[6], segs[1].P3); }
public void PathSegmentAtIndex_ReturnsBezierSegment() { var points = new Vector2[7]; for (int i = 0; i < points.Length; ++i) { points[i] = Vector2.one * i; } var path = new BezierPathSegment[] { new BezierPathSegment() { P0 = points[0], P1 = points[1], P2 = points[2] }, new BezierPathSegment() { P0 = points[3], P1 = points[4], P2 = points[5] }, new BezierPathSegment() { P0 = points[6] } }; var seg0 = VectorUtils.PathSegmentAtIndex(path, 0); Assert.AreEqual(points[0], seg0.P0); Assert.AreEqual(points[1], seg0.P1); Assert.AreEqual(points[2], seg0.P2); Assert.AreEqual(points[3], seg0.P3); var seg1 = VectorUtils.PathSegmentAtIndex(path, 1); Assert.AreEqual(points[3], seg1.P0); Assert.AreEqual(points[4], seg1.P1); Assert.AreEqual(points[5], seg1.P2); Assert.AreEqual(points[6], seg1.P3); }
// Update is called once per frame void Update() { DestroySpriteIfNeeded(); var segments = new BezierPathSegment[segmentInfo.Length]; for (int i = 0; i < segments.Length; ++i) { segments[i].P0 = segmentInfo[i].P0; segments[i].P1 = segmentInfo[i].P1; segments[i].P2 = segmentInfo[i].P2; } var path = new Shape() { Contours = new BezierContour[] { new BezierContour() { Segments = segments } }, PathProps = new PathProperties() { Stroke = new Stroke() { Color = pathColor, HalfThickness = pathHalfThickness } } }; var options = MakeLineOptions(stepDistance); var geo = BuildGeometry(path, options); var sprite = VectorUtils.BuildSprite( geo, 1.0f, VectorUtils.Alignment.Center, Vector2.zero, 128); spriteRenderer.sprite = sprite; }
/// <summary> /// New PolyShape from Unity shape data. /// </summary> /// <param name="unityShape">Shape data</param> /// <param name="shapeTransform">Transform matrix</param> public static PolyShape Create(Shape unityShape, Matrix2D shapeTransform) { PolyShape shape = Create(); int vertexCount = 0; foreach (BezierContour contour in unityShape.Contours) { vertexCount += contour.Segments.Length; } shape.vertices = new Vertex[vertexCount]; for (int i = 0; i < vertexCount; i++) { shape.vertices[i] = new Vertex(); } foreach (BezierContour contour in unityShape.Contours) { for (int i = 0; i < contour.Segments.Length; i++) { BezierPathSegment segment = contour.Segments[i]; shape.vertices[i].position = shapeTransform.MultiplyPoint(segment.P0); shape.vertices[i].exitCP = shapeTransform.MultiplyPoint(segment.P1); shape.vertices[shape.NextIndex(i)].enterCP = shapeTransform.MultiplyPoint(segment.P2); shape.vertices[i].segmentCurves = true; } shape.closed = contour.Closed; } if (unityShape.PathProps.Stroke != null) { shape.colorOutline = unityShape.PathProps.Stroke.Color; } return(shape); }
private Boolean IsClear(BezierPathSegment seg, double minLength, List <Polygon> obstacles) { foreach (Polygon p in obstacles) { if (p.Intersect(seg)) { if (seg.Length < minLength) { return(false); } else { CubicBezier[] newBeziers = seg.cb.Subdivide(0.5); BezierPathSegment newSegA = new BezierPathSegment(newBeziers[0], seg.EndSpeed, seg.StopLine); BezierPathSegment newSegB = new BezierPathSegment(newBeziers[1], seg.EndSpeed, seg.StopLine); return(IsClear(newSegA, minLength, obstacles) && IsClear(newSegB, minLength, obstacles)); } } } return(true); }
public override bool CreateMetaball(float radius1, Vector2 center1) { var distance = Vector2.Distance(center1, center); float u1; var point1 = GameFieldManager.Instance.GetPointOnWall(point1Index); var point2 = GameFieldManager.Instance.GetPointOnWall(point2Index); var perpendicularLine = Vector2.Perpendicular(point1 - point2); var point5 = center1 + perpendicularLine.normalized * radius1; // Check if balls are intersecting if (distance > (Attached ? 100 : distanceBeforeDissolve)) { return(false); } if (distance < radius1 + ballRadius) { if (CheckSide(point2, point1, point5) > 0) { return(false); } // case circles are overlapping u1 = Mathf.Acos((radius1 * radius1 + distance * distance - ballRadius * ballRadius) / (2 * radius1 * distance)); } else { if (CheckSide(point2, point1, point5) > 0) { return(false); } u1 = 0; } // Calculate all angles needed var angleBetweenCenters = AngleBetweenCenters(center, center1); var maxSpread = Mathf.Acos((radius1 - ballRadius) / distance); // Circle 1 (left) var angle1 = angleBetweenCenters + u1 + (maxSpread - u1) * v; var angle2 = angleBetweenCenters - (u1 + (maxSpread - u1) * v); // Calculate the four bezier points var point3 = GetPoint(center1, angle1, radius1); var point4 = GetPoint(center1, angle2, radius1); var tangentPoint1 = GameFieldManager.Instance.GetPointOnWall(point1Index - 1); var tangentPoint2 = GameFieldManager.Instance.GetPointOnWall(point2Index + 1); // Calculate the four handles var totalRadius = radius1 + ballRadius; var d2 = Mathf.Min(v * 10f, Vector2.Distance(point1, point3) / totalRadius); if (float.IsNaN(d2)) { d2 = lastD2; } lastD2 = d2; var r1 = radius1 * d2; var r2 = ballRadius * d2; // Handle point 1 Right surface var handle1 = GetPoint(point1, AngleBetweenCenters(tangentPoint1, point1), r1); // Handle point 2 Left surface var handle2 = GetPoint(point2, AngleBetweenCenters(tangentPoint2, point2), r1); // Handle point 3 Right Ball var handle3 = GetPoint(point3, angle1 - Mathf.PI / 2, r2); // Handle point 4 Left Ball var handle4 = GetPoint(point4, angle2 + Mathf.PI / 2, r2); // Handle point 5 Right var handle5 = point5 + Vector2.Perpendicular(point5).normalized *radius1; // Handle point 5 Left var handle6 = point5 - Vector2.Perpendicular(point5).normalized *radius1; // Define the bezier segments var numberOfPoints = point1Index - point2Index; int index; BezierPathSegment[] bezierSegments; if (distance <= Mathf.Abs(radius1 - ballRadius)) { bezierSegments = new BezierPathSegment[2 + numberOfPoints]; // return true; bezierSegments[0] = new BezierPathSegment { P0 = point1, P1 = handle1, P2 = handle5 }; bezierSegments[1] = new BezierPathSegment { P0 = point5, P1 = handle6, P2 = handle2 }; index = 2; } else { if (BezierCurveUtils.CheckIBezierCurveIntersection( new BezierSegment { P0 = point1, P1 = handle1, P2 = handle3, P3 = point3 }, new BezierSegment { P0 = point2, P1 = handle2, P2 = handle4, P3 = point4 })) { return(false); } bezierSegments = new BezierPathSegment[3 + numberOfPoints]; bezierSegments[0] = new BezierPathSegment { P0 = point1, P1 = handle1, P2 = handle3 }; bezierSegments[1] = new BezierPathSegment { P0 = point3, P1 = point3, P2 = point4 }; bezierSegments[2] = new BezierPathSegment { P0 = point4, P1 = handle4, P2 = handle2 }; index = 3; } for (var i = 0; i < numberOfPoints; i++) { var bezierPointToAdd = GameFieldManager.Instance.GetPointOnWall(point2Index + i); var nextBezierPoint = GameFieldManager.Instance.GetPointOnWall(point2Index + i + 1); bezierSegments[index++] = new BezierPathSegment { P0 = bezierPointToAdd, P1 = bezierPointToAdd, P2 = nextBezierPoint }; } var bezierContour = new BezierContour { Segments = bezierSegments, Closed = false }; // Draw the bezier curve GenerateBezierCurve(new[] { bezierContour }); return(true); }
void Start() { // Prepare the vector path, add it to the vector scene. m_Path = new Shape() { Contours = new BezierContour[] { new BezierContour() { Segments = new BezierPathSegment[2] }, new BezierContour() { Segments = new BezierPathSegment[2] } }, PathProps = new PathProperties() { Stroke = new Stroke() { Color = Color.white, HalfThickness = 0.1f } } }; m_Scene = new Scene() { Root = new SceneNode() { Shapes = new List <Shape> { //m_Path } } }; m_Options = new VectorUtils.TessellationOptions() { StepDistance = 1000.0f, MaxCordDeviation = 0.05f, MaxTanAngleDeviation = 0.05f, SamplingStepSize = 0.01f }; // Instantiate a new mesh, it will be filled with data in Update() m_Mesh = new Mesh(); GetComponent <MeshFilter>().mesh = m_Mesh; // ======================================================================= string path = string.Format(@"D:\WriteByHand\svgs\{0}.svg", 20986); string svg = SVGHelper.readSVG(path); SVGParser.SceneInfo scene_info = SVGParser.ImportSVG(new StringReader(svg)); Scene scene = scene_info.Scene; SceneNode word = scene.Root.Children[1]; // 前半為背景(無 Clipper),後半為寫字筆劃(有 Clipper) List <SceneNode> bg_and_stroke = word.Children; int double_stroke_number = bg_and_stroke.Count; int stroke_number = double_stroke_number / 2; // 筆劃第一筆 SceneNode test_node = bg_and_stroke[stroke_number]; List <Shape> test_shapes = test_node.Shapes; SceneNode test_clipper_node = (test_node.Clipper == null) ? null : test_node.Clipper; List <Shape> test_clippers = new List <Shape>(); if (test_clipper_node != null) { test_clippers = test_clipper_node.Children[0].Shapes; if (test_clippers != null) { print("test_clippers len:" + test_clippers.Count); Shape test_clipper_shape = test_clippers[0]; } else { print("test_clippers is null"); } } else { print("test_clipper_node is null"); } Shape test_stroke = test_shapes[0]; BezierContour[] bezierContours = test_stroke.Contours; BezierPathSegment[] bezierPathSegments = bezierContours[0].Segments; BezierPathSegment point1 = bezierPathSegments[0]; BezierPathSegment point2 = bezierPathSegments[bezierPathSegments.Length - 1]; #region Word scene // 遮罩嘗試 display_scene = new Scene() { Root = new SceneNode() { Children = new List <SceneNode>() { #region One stroke new SceneNode() { Shapes = new List <Shape>() { #region Piece of stroke new Shape() { Contours = new BezierContour[] { new BezierContour() { Segments = new BezierPathSegment[] { point1, point2 } }, //new BezierContour() { // Segments = new BezierPathSegment[2] //} }, PathProps = new PathProperties() { Stroke = new Stroke() { Color = Color.white, HalfThickness = 10f } } } #endregion Piece of stroke end }, Clipper = new SceneNode() { Shapes = new List <Shape>() { #region Piece of clipper test_clippers[0] #endregion Piece of clipper end } } } #endregion One stroke end } } }; #endregion Word scene end StartCoroutine(nextStroke(bg_and_stroke)); }