Ejemplo n.º 1
0
    /// <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);
    }
Ejemplo n.º 2
0
    private static VectorShape ParseContour(BezierContour contour, Matrix2D transform)
    {
        VectorShape vectorShape = new PolyShape(contour);

        vectorShape.TransformBy(transform);

        return(vectorShape);
    }
Ejemplo n.º 3
0
    private BezierContour[] BuildCircleContourWithMask(Rect rect, Vector2 rad, Rect maskRect, Vector2 maskRad)
    {
        var contours = new BezierContour[2];

        contours[0] = VectorUtils.BuildRectangleContour(rect, rad, rad, rad, rad);
        contours[1] = VectorUtils.BuildRectangleContour(maskRect, maskRad, maskRad, maskRad, maskRad);

        return(contours);
    }
Ejemplo n.º 4
0
        public void CubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
        {
            var bezier = new BezierContour(
                new Vector2(x1, y1),
                new Vector2(x2, y2),
                new Vector2(x3, y3)
                );

            Contours.Add(bezier);
        }
Ejemplo n.º 5
0
        public void CubicTo(double x1, double y1, double x2, double y2, double x3, double y3)
        {
            var bezier = new BezierContour(
                new Vector((float)x1, (float)y1),
                new Vector((float)x2, (float)y2),
                new Vector((float)x3, (float)y3)
                );

            Contours.Add(bezier);
        }
    private BezierContour[] BuildRectangleContourWithMask(Rect rect, Rect maskRect)
    {
        // ToDo: Clamp [maskRect] by [rect]

        var contours = new BezierContour[2];

        contours[0] = VectorUtils.BuildRectangleContour(rect, Vector2Zero, Vector2Zero, Vector2Zero, Vector2Zero);
        contours[1] = VectorUtils.BuildRectangleContour(maskRect, Vector2Zero, Vector2Zero, Vector2Zero, Vector2Zero);
        return(contours);
    }
Ejemplo n.º 7
0
    private static VectorShape TryParseShapeToCircle(Shape shape, Matrix2D transform)
    {
        if (shape.Contours.Length > 1)
        {
            return(null);
        }

        BezierContour contour = shape.Contours[0];

        if (contour.Segments.Length < 5)
        {
            return(null);
        }
        if (!contour.Closed)
        {
            return(null);
        }

        BezierSegment[] segments = new BezierSegment[contour.Segments.Length - 1];
        for (int i = 0; i < segments.Length; i++)
        {
            segments[i].P0 = transform.MultiplyPoint(contour.Segments[i].P0);
            segments[i].P1 = transform.MultiplyPoint(contour.Segments[i].P1);
            segments[i].P2 = transform.MultiplyPoint(contour.Segments[i].P2);
            segments[i].P3 = transform.MultiplyPoint(contour.Segments[(i + 1)].P0);
        }

        Rect    shapeBounds = VectorUtils.Bounds(VectorUtils.BezierSegmentsToPath(segments));
        Vector2 center      = shapeBounds.center;
        float   radius      = (shapeBounds.width + shapeBounds.height) / 4f;
        float   error       = radius / 200f;

        for (int i = 0; i < segments.Length; i++)
        {
            if (Mathf.Abs(Vector2.Distance(center, segments[i].P0) - radius) > error)
            {
                return(null);
            }

            Vector2 midpoint = VectorUtils.Eval(segments[i], 0.5f);
            if (Mathf.Abs(Vector2.Distance(center, midpoint) - radius) > error)
            {
                return(null);
            }
        }

        CircleShape circle = new CircleShape(center, radius);

        circle.colorOutline = Color.red;
        return(circle);
    }
Ejemplo n.º 8
0
    /// <summary>
    /// Tessellate the shape into geometry data.
    /// </summary>
    protected override void GenerateGeometry()
    {
        if ((shapeGeometry != null) && (!shapeDirty))
        {
            return;
        }

        Shape circle = new Shape();

        if (closed)
        {
            VectorUtils.MakeCircleShape(circle, position, radius);
        }
        else
        {
            BezierContour contour = new BezierContour();
            contour.Segments = VectorUtils.MakeArc(position, startAngle, sweepAngle, radius);
            circle.Contours  = new BezierContour[] { contour };
        }

        circle.PathProps = new PathProperties()
        {
            Stroke = new Stroke()
            {
                Color         = colorOutline,
                HalfThickness = penSize / Screen.dpi
            }
        };
        if (colorFill != Color.clear)
        {
            circle.Fill = new SolidFill()
            {
                Color = colorFill
            };
        }

        shapeNode = new SceneNode()
        {
            Transform = matrixTransform,
            Shapes    = new List <Shape>
            {
                circle
            }
        };

        tessellationScene.Root = shapeNode;
        shapeGeometry          = VectorUtils.TessellateScene(tessellationScene, tessellationOptions);

        shapeMesh  = null;
        shapeDirty = false;
    }
Ejemplo n.º 9
0
    private static void TessellatePath(BezierContour contour, PathProperties pathProps, List <VectorUtils.Geometry> geoms, VectorUtils.TessellationOptions options)
    {
        if (pathProps.Stroke != null)
        {
            Vector2[] vertices;
            UInt16[]  indices;
            VectorUtils.TessellatePath(contour, pathProps, options, out vertices, out indices);

            var color = pathProps.Stroke.Color;
            geoms.Add(new VectorUtils.Geometry()
            {
                Vertices = vertices, Indices = indices, Color = color
            });
        }
    }
Ejemplo n.º 10
0
    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);
    }
Ejemplo n.º 11
0
    public void CloseContour()
    {
        if (m_Segments.Count > 0)
        {
            var contour = new BezierContour()
            {
                Segments = m_Segments.ToArray()
            };

            m_Contours.Add(contour);
            m_Segments.Clear();

            if (VectorUtils.PathEndsPerfectlyMatch(contour.Segments))
            {
                contour.Closed = true;
            }
        }
    }
Ejemplo n.º 12
0
    /// <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;
    }
Ejemplo n.º 13
0
        private static void TessellatePath(BezierContour contour, PathProperties pathProps, List <Geometry> geoms, TessellationOptions tessellationOptions)
        {
            UnityEngine.Profiling.Profiler.BeginSample("TessellatePath");

            if (pathProps.Stroke != null)
            {
                Vector2[]   vertices;
                UInt16[]    indices;
                Vector2[][] paths;
                ShapeUtils.TessellatePath(contour, pathProps, tessellationOptions, out vertices, out indices, out paths);

                var color = pathProps.Stroke.Color;
                if (indices.Length > 0)
                {
                    geoms.Add(new Geometry()
                    {
                        Vertices = vertices, Indices = indices, Paths = paths, Color = color
                    });
                }
            }

            UnityEngine.Profiling.Profiler.EndSample();
        }
Ejemplo n.º 14
0
        static Vector2[] TraceShape(BezierContour contour, Stroke stroke, TessellationOptions tessellateOptions)
        {
            if (tessellateOptions.StepDistance < Epsilon)
            {
                throw new Exception("stepDistance too small");
            }

            if (contour.Segments.Length < 2)
            {
                return(new Vector2[0]);
            }

            float[] segmentLengths = ShapeUtils.SegmentsLengths(contour.Segments, contour.Closed);

            // Approximate the number of vertices/indices we need to store the results so we reduce memory reallocations during work
            float approxTotalLength = 0.0f;

            foreach (var s in segmentLengths)
            {
                approxTotalLength += s;
            }

            int approxStepCount     = Math.Max((int)(approxTotalLength / tessellateOptions.StepDistance + 0.5f), 2);
            var strokePattern       = stroke != null ? stroke.Pattern : null;
            var strokePatternOffset = stroke != null ? stroke.PatternOffset : 0.0f;

            if (strokePattern != null)
            {
                approxStepCount += strokePattern.Length * 2;
            }

            List <Vector2> verts = new List <Vector2>(approxStepCount); // A little bit possibly for the endings

            var patternIt = new PathPatternIterator(strokePattern, strokePatternOffset);
            var pathIt    = new PathDistanceForwardIterator(contour.Segments, true, tessellateOptions.MaxCordDeviationSquared, tessellateOptions.MaxTanAngleDeviationCosine, tessellateOptions.SamplingStepSize);

            verts.Add(pathIt.EvalCurrent());

            while (!pathIt.Ended)
            {
                float distance        = patternIt.SegmentLength;
                float startingLength  = pathIt.LengthSoFar;
                float unitsRemaining  = Mathf.Min(tessellateOptions.StepDistance, distance);
                bool  endedEntirePath = false;
                for (;;)
                {
                    var result = pathIt.AdvanceBy(unitsRemaining, out unitsRemaining);
                    if (result == PathDistanceForwardIterator.Result.Ended)
                    {
                        endedEntirePath = true;
                        break;
                    }
                    else if (result == PathDistanceForwardIterator.Result.NewSegment)
                    {
                        verts.Add(pathIt.EvalCurrent());
                    }

                    if ((unitsRemaining <= Epsilon) &&
                        !TryGetMoreRemainingUnits(ref unitsRemaining, pathIt, startingLength, distance, tessellateOptions.StepDistance))
                    {
                        break;
                    }

                    if (result == PathDistanceForwardIterator.Result.Stepped)
                    {
                        verts.Add(pathIt.EvalCurrent());
                    }
                }

                // Ending
                if (endedEntirePath)
                {
                    break;
                }
                else
                {
                    verts.Add(pathIt.EvalCurrent());
                }
                patternIt.Advance();
            }

            if ((verts[0] - verts[verts.Count - 1]).sqrMagnitude < Epsilon)
            {
                verts.RemoveAt(verts.Count - 1);
            }
            return(verts.ToArray()); // Why not return verts itself?
        }
Ejemplo n.º 15
0
        public virtual bool CreateMetaball(float radius1, Vector2 center1)
        {
            var distance = Vector2.Distance(center1, Center);

            float u1;
            float u2;

            //    Check if balls are intersecting

            if (distance > (Attached ? 100 : distanceBeforeDissolve) ||
                distance <= Mathf.Abs(radius1 - ballRadius))
            {
                return(false);
            }

            if (distance < radius1 + ballRadius)
            {
                // case circles are overlapping
                u1 = Mathf.Acos((radius1 * radius1 + distance * distance - ballRadius * ballRadius) /
                                (2 * radius1 * distance));
                u2 = Mathf.Acos((ballRadius * ballRadius + distance * distance - radius1 * radius1) /
                                (2 * ballRadius * distance));
            }
            else
            {
                u1 = 0;
                u2 = 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);
            // Circle 2 (right)
            var angle3 = angleBetweenCenters + Mathf.PI - u2 - (Mathf.PI - u2 - maxSpread) * v;
            var angle4 = angleBetweenCenters - (Mathf.PI - u2 - (Mathf.PI - u2 - maxSpread) * v);

            //    Calculate the four bezier points

            var point1 = GetPoint(center1, angle1, radius1);
            var point2 = GetPoint(center1, angle2, radius1);
            var point3 = GetPoint(Center, angle3, ballRadius);
            var point4 = GetPoint(Center, angle4, ballRadius);

            //    Calculate the four handles

            var totalRadius = radius1 + ballRadius;

            var d2 = Mathf.Min(v * 10, Vector2.Distance(point1, point3) / totalRadius);

            var r1 = radius1 * d2;
            var r2 = ballRadius * d2;

            var handle1 = GetPoint(point1, angle1 - Mathf.PI / 2, r1);
            var handle2 = GetPoint(point2, angle2 + Mathf.PI / 2, r1);
            var handle3 = GetPoint(point3, angle3 + Mathf.PI / 2, r2);
            var handle4 = GetPoint(point4, angle4 - Mathf.PI / 2, r2);

            //    Define the bezier segments

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

            var bezierSegments = new[]
            {
                new BezierPathSegment
                {
                    P0 = point1 - (Vector2)transform.parent.position,
                    P1 = handle1 - (Vector2)transform.parent.position,
                    P2 = handle3 - (Vector2)transform.parent.position
                },
                new BezierPathSegment
                {
                    P0 = point3 - (Vector2)transform.parent.position,
                    P1 = point3 - (Vector2)transform.parent.position,
                    P2 = point4 - (Vector2)transform.parent.position
                },
                new BezierPathSegment
                {
                    P0 = point4 - (Vector2)transform.parent.position,
                    P1 = handle4 - (Vector2)transform.parent.position,
                    P2 = handle2 - (Vector2)transform.parent.position
                },
                new BezierPathSegment
                {
                    P0 = point2 - (Vector2)transform.parent.position,
                    P1 = point2 - (Vector2)transform.parent.position,
                    P2 = point1 - (Vector2)transform.parent.position
                }
            };

            //    Define the bezier contour for the shape

            var bezierContour = new BezierContour
            {
                Segments = bezierSegments,
                Closed   = false
            };

            //    Unite everything together

            GenerateBezierCurve(new[] { bezierContour });

            return(true);
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Tessellates a path.
        /// </summary>
        /// <param name="contour">The path to tessellate</param>
        /// <param name="pathProps">The path properties</param>
        /// <param name="tessellateOptions">The tessellation options</param>
        /// <param name="vertices">The resulting vertices</param>
        /// <param name="indices">The resulting triangles</param>
        /// <remarks>
        /// The individual line segments generated during tessellation are made out of a set of ordered vertices. It is important
        /// to honor this ordering so joining and and capping connect properly with the existing vertices without generating dupes.
        /// The ordering assumed is as follows:
        /// The last two vertices of a piece must be such that the first is generated at the end with a positive half-thickness
        /// while the second vertex is at the end too but at a negative half-thickness.
        /// No assumptions are enforced for other vertices before the two last vertices.
        /// </remarks>
        public static void TessellatePath(BezierContour contour, PathProperties pathProps, TessellationOptions tessellateOptions, out Vector2[] vertices, out UInt16[] indices, out Vector2[][] paths)
        {
            if (tessellateOptions.StepDistance < Epsilon)
            {
                throw new Exception("stepDistance too small");
            }

            if (contour.Segments.Length < 2)
            {
                vertices = new Vector2[0];
                indices  = new UInt16[0];
                paths    = new Vector2[0][];
                return;
            }

            UnityEngine.Profiling.Profiler.BeginSample("TessellatePath");

            float[] segmentLengths = ShapeUtils.SegmentsLengths(contour.Segments, contour.Closed);

            // Approximate the number of vertices/indices we need to store the results so we reduce memory reallocations during work
            float approxTotalLength = 0.0f;

            foreach (var s in segmentLengths)
            {
                approxTotalLength += s;
            }

            int approxStepCount = Math.Max((int)(approxTotalLength / tessellateOptions.StepDistance + 0.5f), 2);

            if (pathProps.Stroke.Pattern != null)
            {
                approxStepCount += pathProps.Stroke.Pattern.Length * 2;
            }

            List <Vector2>   verts = new List <Vector2>(approxStepCount * 2 + 32);    // A little bit possibly for the endings
            List <UInt16>    inds  = new List <UInt16>((int)(verts.Capacity * 1.5f)); // Usually every 4 verts represent a quad that uses 6 indices
            List <Vector2[]> pats  = new List <Vector2[]>();

            var patternIt = new PathPatternIterator(pathProps.Stroke.Pattern, pathProps.Stroke.PatternOffset);
            var pathIt    = new PathDistanceForwardIterator(contour.Segments, contour.Closed, tessellateOptions.MaxCordDeviationSquared, tessellateOptions.MaxTanAngleDeviationCosine, tessellateOptions.SamplingStepSize);

            JoiningInfo[] joiningInfo = new JoiningInfo[2];
            HandleNewSegmentJoining(pathIt, patternIt, joiningInfo, pathProps.Stroke.HalfThickness, segmentLengths);

            int rangeIndex = 0;

            while (!pathIt.Ended)
            {
                if (patternIt.IsSolid)
                {
                    TessellateRange(patternIt.SegmentLength, pathIt, patternIt, pathProps, tessellateOptions, joiningInfo, segmentLengths, approxTotalLength, rangeIndex++, verts, inds, pats);
                }
                else
                {
                    SkipRange(patternIt.SegmentLength, pathIt, patternIt, pathProps, joiningInfo, segmentLengths);
                }
                patternIt.Advance();
            }

            vertices = verts.ToArray();
            indices  = inds.ToArray();
            paths    = pats.ToArray();

            UnityEngine.Profiling.Profiler.EndSample();
        }
Ejemplo n.º 17
0
        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);
        }