2009-02-13 22 views
7

Gần đây tôi đã xem qua số this raytracer in LINQ. Chỉ cần tự hỏi nếu có ai có thể đầu đó?Tuyên bố LINQ ấn tượng nhất mà bạn đã gặp phải là gì?

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()); 

Trả lời

6

Tôi nghi ngờ rằng có bất kỳ thứ gì để lên đầu bộ lọc tia. Tôi khá thích my Mandelbrot expression mặc dù:

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

Hãy gọi cho tôi điên, nhưng tôi là một fan hâm mộ lớn của khả năng đọc - vì vậy tôi có xu hướng chỉ có một chuỗi các biểu thức cá nhân-vô tội nhìn tôi sau đó kết hợp. Tất nhiên, nó phụ thuộc vào cách bạn định nghĩa LINQ: nếu bạn có nghĩa là cú pháp truy vấn trong C#, thì tôi không có xu hướng đi quá ... nhưng nếu bạn ngụ ý lập trình meta (tức là mã C# tạo ra một biểu thức LINQ) , tôi đã có một vài ví dụ điển hình:

5

Mads Torgersen demonstrates làm thế nào để viết một biểu thức lambda đệ quy khép kín trong LINQ để tính toán (ví dụ) một thừa:

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) 

Mads ghi chú:

Tôi thậm chí không thể tìm ra cách phá vỡ nó để nó có thể đọc được, vì vậy tôi đã không.

+0

Hấp dẫn (mục nhập blog, tức là - bản thân lambda đang gây khó chịu cho mắt ...) –

Các vấn đề liên quan