Example #1
0
        private static VertexInfo[][] tubeFromCurve(Pt[] pts, double radius, int revSteps)
        {
            var normals = new Pt[pts.Length];

            normals[0] = ((pts[1] - pts[0]) * pt(0, 1, 0)).Normalize() * radius;
            for (int i = 1; i < pts.Length - 1; i++)
            {
                normals[i] = normals[i - 1].ProjectOntoPlane((pts[i + 1] - pts[i]) + (pts[i] - pts[i - 1])).Normalize() * radius;
            }
            normals[pts.Length - 1] = normals[pts.Length - 2].ProjectOntoPlane(pts[pts.Length - 1] - pts[pts.Length - 2]).Normalize() * radius;

            var axes = pts.Select((p, i) =>
                                  i == 0 ? new { Start = pts[0], End = pts[1] } :
                                  i == pts.Length - 1 ? new { Start = pts[pts.Length - 2], End = pts[pts.Length - 1] } :
                                  new { Start = p, End = p + (pts[i + 1] - p) + (p - pts[i - 1]) }).ToArray();

            return(Enumerable.Range(0, pts.Length)
                   .Select(ix => new { Axis = axes[ix], Perp = pts[ix] + normals[ix], Point = pts[ix] })
                   .Select(inf => Enumerable.Range(0, revSteps)
                           .Select(i => 360 * i / revSteps)
                           .Select(angle => inf.Perp.Rotate(inf.Axis.Start, inf.Axis.End, angle))
                           .Select(p => new VertexInfo {
                Point = p, Normal = p - inf.Point
            }).Reverse().ToArray())
                   .ToArray());
        }
 public static Pt RotateX(this Pt p, double angle)
 {
     return(new Pt(p.X, p.Y * cos(angle) - p.Z * sin(angle), p.Y * sin(angle) + p.Z * cos(angle)));
 }
 public static IEnumerable <Pt[]> Move(this IEnumerable <Pt[]> faces, Pt by)
 {
     return(faces.Select(face => Move(face, by)));
 }
 public static Pt[][] Move(this Pt[][] faces, Pt by)
 {
     return(faces.Select(face => Move(face, by)).ToArray());
 }
 public static IEnumerable <Pt> Move(this IEnumerable <Pt> face, Pt by)
 {
     return(face.Select(p => p + by));
 }
 public static Pt[] Move(this Pt[] face, Pt by)
 {
     return(face.Select(p => p + by).ToArray());
 }
Example #7
0
        public static Mesh GenerateWire(System.Random rnd, int lengthIndex, int color, WirePiece piece, bool highlight)
        {
            var length             = GetWireLength(lengthIndex);
            var thickness          = highlight ? _wireRadiusHighlight : _wireRadius;
            var firstControlHeight = highlight ? _firstControlHeightHighlight : _firstControlHeight;
            var interpolateHeight  = highlight ? _interpolateHeightHighlight : _interpolateHeight;

            var start        = pt(0, 0, 0);
            var startControl = pt(length / 10, 0, firstControlHeight);
            var endControl   = pt(length * 9 / 10, 0, firstControlHeight);
            var end          = pt(length, 0, 0);
            var numSegments  = new[] { 6, 4, 4 }[lengthIndex];

            var bézierSteps  = 16;
            var tubeRevSteps = 16;

            var interpolateStart = pt(0, 0, interpolateHeight);
            var interpolateEnd   = pt(length, 0, interpolateHeight);

            var intermediatePoints = newArray(numSegments - 1, i => interpolateStart + (interpolateEnd - interpolateStart) * (i + 1) / numSegments + pt(rnd.NextDouble() - .5, rnd.NextDouble() - .5, rnd.NextDouble() - .5) * _wireMaxSegmentDeviation);
            var deviations         = newArray(numSegments - 1, _ => pt(rnd.NextDouble(), rnd.NextDouble(), rnd.NextDouble()) * _wireMaxBézierDeviation);

            if (piece == WirePiece.Uncut)
            {
                var points =
                    new[] { new { ControlBefore = default(Pt), Point = start, ControlAfter = startControl } }
                .Concat(intermediatePoints.Select((p, i) => new { ControlBefore = p - deviations[i], Point = p, ControlAfter = p + deviations[i] }))
                .Concat(new[] { new { ControlBefore = endControl, Point = end, ControlAfter = default(Pt) } })
                .SelectConsecutivePairs(false, (one, two) => bézier(one.Point, one.ControlAfter, two.ControlBefore, two.Point, bézierSteps))
                .SelectMany((x, i) => i == 0 ? x : x.Skip(1))
                .ToArray();
                return(toMesh(createFaces(false, true, tubeFromCurve(points, thickness, tubeRevSteps)), _colors[color]));
            }

            var partialWire = new Func <IEnumerable <CPC>, IEnumerable <VertexInfo[]> >(pts =>
            {
                var points = pts
                             .SelectConsecutivePairs(false, (one, two) => bézier(one.Point, one.ControlAfter, two.ControlBefore, two.Point, bézierSteps))
                             .SelectMany((x, i) => i == 0 ? x : x.Skip(1))
                             .ToArray();

                var reserveForCopper = 6;
                var discardCopper    = 2;

                if (piece == WirePiece.Cut)
                {
                    var tube      = tubeFromCurve(points, thickness, tubeRevSteps).SkipLast(reserveForCopper).ToArray();
                    var capCenter = points[points.Length - 1 - reserveForCopper];
                    var normal    = capCenter - points[points.Length - 2 - reserveForCopper];
                    var cap       = tube[tube.Length - 1].SelectConsecutivePairs(true, (v1, v2) => new[] { capCenter, v2.Point, v1.Point }.Select(p => new VertexInfo {
                        Point = p, Normal = normal
                    }).ToArray()).ToArray();
                    return(createFaces(false, true, tube).Concat(cap));
                }
                else
                {
                    var copper          = tubeFromCurve(points.TakeLast(reserveForCopper + 2).SkipLast(discardCopper).ToArray(), thickness / 2, tubeRevSteps).Skip(1).ToArray();
                    var copperCapCenter = points[points.Length - 1 - discardCopper];
                    var copperNormal    = copperCapCenter - points[points.Length - 2];
                    var copperCap       = copper[copper.Length - 1].SelectConsecutivePairs(true, (v1, v2) => new[] { copperCapCenter, v2.Point, v1.Point }.Select(p => new VertexInfo {
                        Point = p, Normal = copperNormal
                    }).ToArray()).ToArray();
                    return(createFaces(false, true, copper).Concat(copperCap));
                }
            });

            var           rotAngle     = (rnd.NextDouble() * 7 + 5) * (rnd.Next(2) == 0 ? -1 : 1);
            var           rotAxisStart = new Pt(0, 0, 0);
            var           rotAxisEnd   = new Pt(rnd.NextDouble() * .01, rnd.NextDouble() * .01, 1);
            Func <Pt, Pt> rot          = p => p.Rotate(rotAxisStart, rotAxisEnd, rotAngle);
            var           beforeCut    =
                new[] { new CPC {
                            ControlBefore = default(Pt), Point = start, ControlAfter = startControl
                        } }
            .Concat(intermediatePoints.Take(numSegments / 2).Select((p, i) => new CPC {
                ControlBefore = rot(p - deviations[i]), Point = rot(p), ControlAfter = rot(p + deviations[i])
            }));
            var bcTube = partialWire(beforeCut);

            var cutOffPoint = (numSegments - 1) / 2;

            rotAngle     = (rnd.NextDouble() * 7 + 5) * (rnd.Next(2) == 0 ? -1 : 1);
            rotAxisStart = new Pt(length, 0, 0);
            rotAxisEnd   = new Pt(length + rnd.NextDouble() * .01, rnd.NextDouble() * .01, 1);
            var afterCut =
                new[] { new CPC {
                            ControlBefore = default(Pt), Point = end, ControlAfter = endControl
                        } }
            .Concat(intermediatePoints.Skip(cutOffPoint).Select((p, i) => new CPC {
                ControlBefore = rot(p + deviations[i + cutOffPoint]), Point = rot(p), ControlAfter = rot(p - deviations[i + cutOffPoint])
            }).Reverse());
            var acTube = partialWire(afterCut);

            return(toMesh(bcTube.Concat(acTube).ToArray(), _colors[color]));
        }
Example #8
0
 private static IEnumerable <Pt> bézier(Pt start, Pt control1, Pt control2, Pt end, int steps)
 {
     return(Enumerable.Range(0, steps)
            .Select(i => (double)i / (steps - 1))
            .Select(t => pow(1 - t, 3) * start + 3 * pow(1 - t, 2) * t * control1 + 3 * (1 - t) * t * t * control2 + pow(t, 3) * end));
 }