【问题标题】:What is the most impressive LINQ statement that you have come across?您遇到的最令人印象深刻的 LINQ 语句是什么?
【发布时间】:2012-05-04 11:33:43
【问题描述】:

我最近遇到了this raytracer in LINQ。只是想知道是否有人能做到这一点?

var pixelsQuery =
from y in Enumerable.Range(0, screenHeight)
let recenterY = -(y - (screenHeight / 2.0)) / (2.0 * screenHeight)
select from x in Enumerable.Range(0, screenWidth)
       let recenterX = (x - (screenWidth / 2.0)) / (2.0 * screenWidth)
       let point = Vector.Norm(Vector.Plus(scene.Camera.Forward, 
                                           Vector.Plus(Vector.Times(recenterX, scene.Camera.Right),
                                                       Vector.Times(recenterY, scene.Camera.Up))))
       let ray = new Ray { Start = scene.Camera.Pos, Dir = point }
       let computeTraceRay = (Func<Func<TraceRayArgs, Color>, Func<TraceRayArgs, Color>>)
        (f => traceRayArgs =>
         (from isect in
              from thing in traceRayArgs.Scene.Things
              select thing.Intersect(traceRayArgs.Ray)
          where isect != null
          orderby isect.Dist
          let d = isect.Ray.Dir
          let pos = Vector.Plus(Vector.Times(isect.Dist, isect.Ray.Dir), isect.Ray.Start)
          let normal = isect.Thing.Normal(pos)
          let reflectDir = Vector.Minus(d, Vector.Times(2 * Vector.Dot(normal, d), normal))
          let naturalColors = 
              from light in traceRayArgs.Scene.Lights
              let ldis = Vector.Minus(light.Pos, pos)
              let livec = Vector.Norm(ldis)
              let testRay = new Ray { Start = pos, Dir = livec }
              let testIsects = from inter in
                                   from thing in traceRayArgs.Scene.Things
                                   select thing.Intersect(testRay)
                               where inter != null
                               orderby inter.Dist
                               select inter
              let testIsect = testIsects.FirstOrDefault()
              let neatIsect = testIsect == null ? 0 : testIsect.Dist
              let isInShadow = !((neatIsect > Vector.Mag(ldis)) || (neatIsect == 0))
              where !isInShadow
              let illum = Vector.Dot(livec, normal)
              let lcolor = illum > 0 ? Color.Times(illum, light.Color) : Color.Make(0, 0, 0)
              let specular = Vector.Dot(livec, Vector.Norm(reflectDir))
              let scolor = specular > 0 
                           ? Color.Times(Math.Pow(specular, isect.Thing.Surface.Roughness), light.Color) 
                           : Color.Make(0, 0, 0)
              select Color.Plus(Color.Times(isect.Thing.Surface.Diffuse(pos), lcolor),
                                Color.Times(isect.Thing.Surface.Specular(pos), scolor))
          let reflectPos = Vector.Plus(pos, Vector.Times(.001, reflectDir))
          let reflectColor = 
              traceRayArgs.Depth >= MaxDepth
              ? Color.Make(.5, .5, .5)
              : Color.Times(isect.Thing.Surface.Reflect(reflectPos), 
                            f(new TraceRayArgs(new Ray { Start = reflectPos, Dir = reflectDir }, 
                                               traceRayArgs.Scene, 
                                               traceRayArgs.Depth + 1)))
          select naturalColors.Aggregate(reflectColor, (color, natColor) => Color.Plus(color, natColor)))
                              .DefaultIfEmpty(Color.Background).First())
       let traceRay = Y(computeTraceRay)
       select new { X = x, Y = y, Color = traceRay(new TraceRayArgs(ray, scene, 0)) };

foreach (var row in pixelsQuery)
    foreach (var pixel in row)
        setPixel(pixel.X, pixel.Y, pixel.Color.ToDrawingColor());

【问题讨论】:

    标签: .net linq


    【解决方案1】:

    我怀疑光线追踪器上面有什么东西。不过我很喜欢my Mandelbrot expression

    from row in Enumerable.Range(0, ImageHeight)
    from col in Enumerable.Range(0, ImageWidth)
    // Work out the initial complex value from the row and column
    let c = new Complex((col * SampleWidth) / ImageWidth + OffsetX,
                        (row * SampleHeight) / ImageHeight + OffsetY)
    // Work out the number of iterations
    select Generate(c, x => x * x + c).TakeWhile(x => x.SquareLength < 4)
                                      .Take(MaxIterations)
                                      .Count() into count
    // Map that to an appropriate byte value
    select (byte)(count == MaxIterations ? 0 : (count % 255) + 1); 
    

    【讨论】:

      【解决方案2】:

      Mads Torgersen demonstrates 如何在 LINQ 中编写一个自包含的递归 lambda 表达式来计算(例如)阶乘:

      i => new Func<Func<int,int>,Func<int,int>>(fac => x => x == 0 ? 1 : x * fac(x
      - 1))(new SelfApplicable<Func<Func<Func<int,int>,Func<int,int>>,Func<int,int>
      >>(y => f => x => f(y(y)(f))(x))(y => f => x => f(y(y)(f))(x))(fac => x => x
      == 0 ? 1 : x * fac(x - 1)))(i)
      

      疯狂笔记:

      我什至不知道如何换行以使其接近可读,所以我没有。

      【讨论】:

      • 引人入胜(博客条目,即 - lambda 本身令人眼花缭乱......)
      【解决方案3】:

      说我疯了,但我是可读性的忠实拥护者 - 所以我倾向于将一系列看起来很独立的表达组合起来。当然,这取决于您如何定义 LINQ:如果您指的是 C# 中的查询语法,那么我不会过分……但如果您指的是元编程(即 创建的 C# 代码 一个 LINQ 表达式),我有几个很好的例子:

      【讨论】:

        猜你喜欢
        • 2010-11-15
        • 2011-09-04
        • 1970-01-01
        • 2013-01-23
        • 2011-12-22
        • 1970-01-01
        • 2010-11-26
        • 1970-01-01
        • 2016-02-01
        相关资源
        最近更新 更多