Beispiel #1
0
        //--------------------------------------------------------------
        #region Methods
        //--------------------------------------------------------------

        /// <inheritdoc/>
        internal override void Flatten(ArrayList <Vector3F> vertices, ArrayList <int> strokeIndices, ArrayList <int> fillIndices)
        {
            Triangulator triangulator    = null;
            var          segmentVertices = ResourcePools <Vector2F> .Lists.Obtain();

            var segmentStartIndices = ResourcePools <int> .Lists.Obtain();

            Vector2F previousVertex = new Vector2F(float.NaN);

            foreach (var curve in Segments)
            {
                segmentVertices.Clear();
                curve.Flatten(segmentVertices, MaxNumberOfIterations, Tolerance);

                // Flatten should always return an even number of vertices. But if Flatten()
                // is erroneous we simply ignore the last vertex.
                int vertexCount = segmentVertices.Count;
                if (vertexCount % 2 != 0)
                {
                    vertexCount--;
                }

                if (vertexCount < 2)
                {
                    continue;
                }

                Vector2F segmentStartVertex = segmentVertices[0];
                bool     isNewShape;
                int      segmentStartIndex; // Start of current segment in 'vertices'.
                if (segmentStartVertex == previousVertex)
                {
                    // Continuation of current shape: Skip first vertex of segment.
                    isNewShape        = false;
                    segmentStartIndex = vertices.Count - 1;
                }
                else
                {
                    // Start of new shape: Previous segments are no longer needed.
                    isNewShape = true;
                    segmentStartIndices.Clear();
                    segmentStartIndex = vertices.Count;
                }

                // Check for closed shapes.
                Vector2F segmentEndVertex = segmentVertices[segmentVertices.Count - 1];
                bool     isClosedShape    = false;
                int      shapeStartIndex  = -1;

                // Check if current segment is closed.
                if (vertexCount > 2 && segmentStartVertex == segmentEndVertex)
                {
                    // Closed shape found.
                    isClosedShape   = true;
                    shapeStartIndex = segmentStartIndex;
                }

                // Check if last n segments are closed.
                if (!isClosedShape)
                {
                    int      numberOfSegments = segmentStartIndices.Count;
                    var      vertexArray      = vertices.Array;
                    Vector3F v = new Vector3F(segmentEndVertex.X, segmentEndVertex.Y, 0);
                    for (int i = 0; i < numberOfSegments; i++)
                    {
                        int startIndex = segmentStartIndices[i];
                        if (v == vertexArray[startIndex])
                        {
                            // Closed shape found.
                            isClosedShape   = true;
                            shapeStartIndex = startIndex;
                            break;
                        }
                    }
                }

                if (isClosedShape)
                {
                    segmentStartIndices.Clear();
                }
                else
                {
                    segmentStartIndices.Add(segmentStartIndex);
                }

                CommitVertices(segmentVertices, isNewShape, isClosedShape, vertices);

                if (IsStroked(curve))
                {
                    // Apply stroke.
                    int lineCount = vertexCount / 2;
                    Stroke(segmentStartIndex, lineCount, isClosedShape, shapeStartIndex, strokeIndices);
                }

                if (isClosedShape && IsFilled)
                {
                    // Apply fill.
                    Fill(vertices, shapeStartIndex, fillIndices, ref triangulator);
                }

                previousVertex.X = segmentEndVertex.X;
                previousVertex.Y = segmentEndVertex.Y;
            }

            ResourcePools <Vector2F> .Lists.Recycle(segmentVertices);

            ResourcePools <int> .Lists.Recycle(segmentStartIndices);

            if (triangulator != null)
            {
                triangulator.Recycle();
            }
        }