コード例 #1
0
        public void Line(double x0, double y0, double x1, double y1, Color4 color)
        {
            var v0 = new LineArtVertex(new Vector2d(x0, y0), color: color);
            var v1 = new LineArtVertex(new Vector2d(x1, y1), color: color);

            SubmitOpenPath(new LineSegment(v0, v1));
        }
コード例 #2
0
        RawJoin RawJoinAt(LineArtVertex v)
        {
            var along = (V1.Pos - V0.Pos).Normalized();
            var side  = along.PerpendicularRight;

            // OPT: vector math
            return(new RawJoin(side * v.StrokeWidth, along, side * -v.StrokeWidth, along));
        }
コード例 #3
0
 public PathSegment(LineArtVertex v0, LineArtVertex v1)
 {
     V0 = v0;
     V1 = v1;
     // These are normally set by Path below
     Before  = null;
     After   = null;
     Closing = false;
 }
コード例 #4
0
        // TODO: These don't have a way to specify line thickness...
        public void Circle(double x, double y, double radius, Color4 color, int?numSegments = null)
        {
            var vertex = new LineArtVertex(new Vector2d(x + radius, y), color);
            var verts  = new PathSegment[] {
                new ArcSegment(vertex, vertex, new Vector2d(x, y), true, numSegments)
            };

            SubmitClosedPath(verts);
        }
コード例 #5
0
 public ArcSegment(LineArtVertex v0, LineArtVertex v1, Vector2d center,
                   bool?clockwise = null, int?requestedSegments = null)
     : base(v0, v1)
 {
     Center    = center;
     Clockwise = clockwise ?? SMath.CrossZ(V0.Pos - Center, V1.Pos - Center) < 0;
     // XXX: Might be better to come up with something based on RADIANS_PER_PIECE
     // and the angle span of the arc.
     RequestedSegments = requestedSegments ?? DEFAULT_SEGMENTS;
 }
コード例 #6
0
        public void PolyLineUniform(IEnumerable <Vector2d> positions, Color4 color)
        {
            var verts = new List <LineArtVertex>();

            foreach (var pos in positions)
            {
                var v = new LineArtVertex(pos, color: color);
                verts.Add(v);
            }
            PolyLine(verts);
        }
コード例 #7
0
        public void Arc(double cx, double cy, double radius, double sweep, Color4 color, double startAngle = 0.0,
                        int?numSegments = null)
        {
            var pos0 = SMath.Rotate(Vector2d.UnitX, startAngle) * radius;
            var pos1 = SMath.Rotate(Vector2d.UnitX, startAngle + sweep) * radius;
            //Log.Message("Start angle {0}, sweep {1}, radius {2}, pos0 {3}, pos1 {4}, length1 {5}, length2 {6}",
            //                  startAngle, sweep, radius, pos0, pos1, pos0.Length, pos1.Length);
            var v0 = new LineArtVertex(pos0, color: color);
            var v1 = new LineArtVertex(pos1, color: color);

            SubmitOpenPath(new ArcSegment(v1, v0, new Vector2d(cx, cy), true, numSegments));
        }
コード例 #8
0
        public RawJoin RawJoinAt(LineArtVertex v)
        {
            var side = (v.Pos - Center).Normalized();

            if (Clockwise)
            {
                side = -side;
            }

            var along = -side.PerpendicularRight;

            return(new RawJoin(side * v.StrokeHalfWidth, along,
                               side * -v.StrokeHalfWidth, along));
        }
コード例 #9
0
        public override void TesselateArc(ArcSegment arc)
        {
            AdvanceToSegmentIn(arc);
            foreach (var pt in arc.GenerateInteriorPoints())
            {
                var interior = pt.Item1;
                var sideR    = pt.Item2;
                var sideL    = pt.Item3;

                var verts = new LineArtVertex[] {
                    new LineArtVertex(interior.Pos + sideR, color: interior.Color),
                    new LineArtVertex(interior.Pos + sideL, color: interior.Color)
                };

                AdvanceTo(verts);
            }
            AdvanceToSegmentOut(arc);
        }
コード例 #10
0
 void AdvanceToSegmentOut(PathSegment seg)
 {
     if (seg.After == null)
     {
         var rjOut     = seg.RawJoinOut();
         var nextVerts = new LineArtVertex[] {
             new LineArtVertex(seg.Pos1 + rjOut.SideR, color: seg.V1.Color),
             new LineArtVertex(seg.Pos1 + rjOut.SideL, color: seg.V1.Color),
         };
         if (seg.Cap)
         {
             var cap      = SquarishCap(rjOut, +1.0);
             var cap0     = cap.Item1;
             var cap1     = cap.Item2;
             var endVerts = new LineArtVertex[] {
                 new LineArtVertex(seg.Pos1 + cap0, color: seg.V1.Color),
                 new LineArtVertex(seg.Pos1 + cap1, color: seg.V1.Color)
             };
             AdvanceTo(nextVerts);
             AdvanceTo(endVerts);
         }
         else
         {
             AdvanceTo(nextVerts);
         }
     }
     else if (seg.Closing)
     {
         CloseRoad();
     }
     else
     {
         var jn        = MiterishJoin(seg.RawJoinOut(), seg.After.RawJoinIn());
         var sideR     = jn.Item1;
         var sideL     = jn.Item2;
         var nextVerts = new LineArtVertex[] {
             new LineArtVertex(seg.Pos1 + sideR, color: seg.V1.Color),
             new LineArtVertex(seg.Pos1 + sideL, color: seg.V1.Color)
         };
         AdvanceTo(nextVerts);
     }
 }
コード例 #11
0
 void AdvanceToSegmentIn(PathSegment seg)
 {
     if (seg.Before == null)
     {
         var rjIn      = seg.RawJoinIn();
         var nextVerts = new LineArtVertex[] {
             new LineArtVertex(seg.Pos0 + rjIn.SideR, color: seg.V0.Color),
             new LineArtVertex(seg.Pos0 + rjIn.SideL, color: seg.V0.Color),
         };
         if (seg.Cap)
         {
             var cap        = SquarishCap(rjIn, -1.0);
             var cap0       = cap.Item1;
             var cap1       = cap.Item2;
             var beginVerts = new LineArtVertex[] {
                 new LineArtVertex(seg.Pos0 + cap0, color: seg.V0.Color),
                 new LineArtVertex(seg.Pos0 + cap1, color: seg.V0.Color),
             };
             BeginRoad(beginVerts);
             AdvanceTo(nextVerts);
         }
         else
         {
             // No cap
             BeginRoad(nextVerts);
         }
     }
     else if (seg.Before.Closing || (lastIndices == null))
     {
         // The RHS of the disjunction is in case we start tessellating in the middle of a
         // path somehow.  That feels like it might be useful later.
         var jn    = MiterishJoin(seg.Before.RawJoinOut(), seg.RawJoinIn());
         var sideR = jn.Item1;
         var sideL = jn.Item2;
         var verts = new LineArtVertex[] {
             new LineArtVertex(seg.Pos0 + sideR, color: seg.V0.Color),
             new LineArtVertex(seg.Pos0 + sideL, color: seg.V0.Color),
         };
         BeginRoad(verts);
     }
 }
コード例 #12
0
 public void AddVertex(LineArtVertex v)
 {
     Vertexes.Add(v);
 }
コード例 #13
0
        GenerateInteriorPoints()
        {
            // Everything is in radians in this function because converting to degrees and back would
            // be rather silly.

            //var offset0 = V0.Pos - Center;
            //var offset1 = V1.Pos - Center;
            var angle0 = Math.Atan2(V0.Pos.Y - Center.Y, V0.Pos.X - Center.X);
            var angle1 = Math.Atan2(V1.Pos.Y - Center.Y, V1.Pos.X - Center.X);

            if (Clockwise && (angle0 <= angle1))
            {
                angle1 -= SMath.TAU;
            }
            else if ((!Clockwise) && (angle0 >= angle1))
            {
                angle1 += SMath.TAU;
            }
            var angleStep = (angle1 - angle0) / RequestedSegments;

            var radius0 = (V0.Pos - Center).Length;
            var radius1 = (V1.Pos - Center).Length;
            //Log.Message("Radius 0 {0}, Radius 1 {1}", radius0, radius1);
            var radiusStep = (radius1 - radius0) / RequestedSegments;

            var strokeHalfWidth0    = V0.StrokeHalfWidth;
            var strokeHalfWidth1    = V1.StrokeHalfWidth;
            var strokeHalfWidthStep = strokeHalfWidth1 - strokeHalfWidth0;

            // This is alpha not in terms of color blending but rather in terms of
            // how far we are through a lerp.
            var alphaStep = 1.0 / RequestedSegments;

            var currentAlpha           = 0.0;
            var currentAngle           = angle0;
            var currentRadius          = radius0;
            var currentX               = Math.Cos(currentAngle) * radius0;
            var currentY               = Math.Sin(currentAngle) * radius0;
            var currentStrokeHalfWidth = strokeHalfWidth0;

            for (int i = 1; i < RequestedSegments; i++)
            {
                currentAlpha  += alphaStep;
                currentAngle  += angleStep;
                currentRadius += radiusStep;

                currentX = Math.Cos(currentAngle) * currentRadius;
                currentY = Math.Sin(currentAngle) * currentRadius;
                currentStrokeHalfWidth += strokeHalfWidthStep;

                //Console.WriteLine("Generating point at x {0}, y {1}, radius {2}, angle {3}", currentX, currentY, currentRadius, currentAngle);

                var currentOffset   = new Vector2d(currentX, currentY);
                var currentPosition = currentOffset + Center;
                var currentVertex   = LineArtVertex.Lerp(V0, V1, currentAlpha, pos: currentPosition);
                var currentNormal   = currentOffset.Normalized();
                var inner           = currentNormal * currentStrokeHalfWidth;
                var outer           = -inner;
                //Log.Message("Current angle: {0}, X: {1}, Y: {2}, center: {3}, alpha: {4}, angle0: {5}, angle1: {6}",
                //	currentAngle, currentX, currentY, Center, currentAlpha, angle0, angle1);
                yield return(new Tuple <LineArtVertex, Vector2d, Vector2d>(currentVertex, outer, inner));
            }

            /*
             * var rel0 = V0.Pos - Center;
             * var rel1 = V1.Pos - Center;
             * var radius0 = rel0.Length;
             * var radius1 = rel1.Length;
             * var angle0 = Math.Atan2(V0.Pos.Y - Center.Y, V0.Pos.X - Center.X);
             * var angle1 = Math.Atan2(V1.Pos.Y - Center.Y, V1.Pos.X - Center.X);
             * if (Clockwise && angle0 <= angle1) {
             *      angle1 -= SMath.TAU;
             * } else if ((!Clockwise) && (angle0 >= angle1)) {
             *      angle1 += SMath.TAU;
             * }
             * var nPieces = RequestedSegments ?? Math.Max(3, (int)Math.Ceiling(Math.Abs(angle1 - angle0) / RADIANS_PER_PIECE));
             * var deltaAlpha = 1.0 / nPieces;
             * var deltaRadius = (radius1 - radius0) * deltaAlpha;
             * var deltaAngle = (angle1 - angle0) * deltaAlpha;
             * var deltaStrokeHalf = (V1.StrokeHalfWidth - V0.StrokeHalfWidth) * deltaAlpha;
             *
             * var sinDA = Math.Sin(deltaAngle);
             * var cosDA = Math.Cos(deltaAngle);
             * var rel0Unit = rel0.Normalized();
             *
             * var unitX = rel0Unit.X;
             * var unitY = rel0Unit.Y;
             * var curRadius = radius0;
             * var curStrokeHalf = V0.StrokeHalfWidth;
             * if (Clockwise) {
             *      curStrokeHalf = -curStrokeHalf;
             *      deltaStrokeHalf = -deltaStrokeHalf;
             * }
             * // We only need to generate nPieces-1 points because the start and end points are both excluded.
             * // This might be more numerically stable than the tan/cos method and still doesn't take a sin/cos
             * // every iteration.  We shouldn't be doing this very often anyway.
             * for (int i = 1; i < nPieces; i++) {
             *      curStrokeHalf += deltaStrokeHalf;
             *      curRadius += deltaRadius;
             *      unitX = unitX * cosDA - unitY * sinDA;
             *      unitY = unitX * sinDA - unitY * cosDA;
             *      var interiorPos = new Vector2d(Center.X + unitX * curRadius, Center.Y + unitY * curRadius);
             *      var interior = LineArtVertex.Lerp(V0, V1, i * deltaAlpha, pos: interiorPos);
             *      var sideR = new Vector2d(unitX * curStrokeHalf, unitY * curStrokeHalf);
             *      yield return new Tuple<LineArtVertex, Vector2d, Vector2d>(interior, sideR, -sideR);
             * }
             * yield break;
             */
        }
コード例 #14
0
 public LineSegment(LineArtVertex v0, LineArtVertex v1) : base(v0, v1)
 {
     Cap = true;
 }