예제 #1
0
        /// <summary>Generates a stroke now using these settings.
        /// Note that the given path may be modified.</summary>
        public void Generate(VectorPath path)
        {
            // First, simplify the path (eliminates loops etc):
            path.SimplifyCurve();

            // Always recalculate bounds:
            path.RecalculateBounds();

            // For each line, we can now generate the two
            // offset curves and sample them individually.

            float halfWidth = Width / 2f;

            // Tidy values:
            OuterLength = 0f;
            InnerLength = 0f;
            InnerCount  = 0;
            OuterCount  = 0;
            float nx;
            float ny;

            // Are we using linejoin?
            bool lineJoinActive = (LineJoinMode & StrokeLineMode.JoinActive) != 0;

            VectorPoint current = path.FirstPathNode;

            while (current != null)
            {
                VectorLine line = current as VectorLine;

                // Set the current line:
                CurrentLine = line;

                if (line == null)
                {
                    // Move to. Complete the previous contour:
                    CompleteContour((current as MoveToPoint).ClosePoint != null);

                    // Go to next:
                    current = current.Next;
                    continue;
                }

                if (lineJoinActive)
                {
                    // Get start normal:
                    line.StartNormal(out nx, out ny);
                    StartNormal = new Vector2(nx, ny);
                }

                // First of line:
                bool applyLineJoin = AtLeastOneLine && lineJoinActive;

                if (applyLineJoin)
                {
                    // Compare StartNormal with EndNormal and figure out if we're adding extra verts to
                    // inner or outer.

                    // Original point:
                    OriginalLinePoint = new Vector2(
                        current.Previous.X,
                        current.Previous.Y
                        );

                    // Get the angle between them:
                    float angle = (float)System.Math.Atan2(
                        StartNormal.x * EndNormal.y - StartNormal.y * EndNormal.x,
                        StartNormal.x * EndNormal.x + StartNormal.y * EndNormal.y
                        );

                    // If we're in miter mode, find the miter length.
                    // If it exceeds the miter limit, set angle to 0 so we just end up with a bevel.
                    if (LineJoinMode == StrokeLineMode.Miter)
                    {
                        // Compute the miter length now:
                        float miterRatio = 1f / (float)System.Math.Sin(angle / 2f);

                        if (miterRatio > MiterLimit || -miterRatio > MiterLimit)
                        {
                            // Out of range!
                            angle = 0f;
                        }
                        else
                        {
                            // Set the miter length now:
                            MiterLength = miterRatio * halfWidth;
                        }
                    }

                    LineAngle = angle;

                    // Very close to zero -> Do nothing (this is ~5 degrees):
                    if (angle > 0.08f)
                    {
                        // Apply join to outer:
                        ApplyLineJoinNow = true;
                        applyLineJoin    = false;
                    }
                    else if (angle > -0.08f)
                    {
                        applyLineJoin = false;
                    }

                    // Else apply join to inner (by leaving applyLineJoin true).
                }


                // Change to outer curve:
                Outer = true;

                // Extrude and sample it:
                current.ExtrudeAndSample(path, halfWidth, this);

                // Increase length so far:
                OuterLength += line.Length;

                // Change to inner curve:
                Outer = false;

                if (applyLineJoin)
                {
                    // Apply join to inner:
                    ApplyLineJoinNow = true;
                }

                // Extrude and sample it:
                current.ExtrudeAndSample(path, -halfWidth, this);

                // Increase length so far:
                InnerLength += line.Length;

                if (lineJoinActive)
                {
                    // Get end normal:
                    line.EndNormal(out nx, out ny);
                    EndNormal = new Vector2(nx, ny);
                }

                // We've seen at least one line:
                AtLeastOneLine = true;

                // Next:
                current = current.Next;
            }

            // Complete the final contour:
            CompleteContour(path.LatestPathNode.IsClose);
        }