@@ -77,7 +77,7 @@ public static Point TransformPoint(
7777 /// <param name="gridType">Selected type of grid</param>
7878 /// <param name="width">Width of output image</param>
7979 /// <param name="height">Height of output image</param>
80- /// <returns>List of lines</returns>
80+ /// <returns>List of lines; points coordinates are in normalized range [0..1] </returns>
8181 public static IEnumerable < Line > CreateGrid ( GridType gridType , double width , double height )
8282 {
8383 switch ( gridType )
@@ -170,56 +170,133 @@ public static IEnumerable<Line> CreateGrid(GridType gridType, double width, doub
170170
171171 case GridType . FibonacciRectangles :
172172 {
173- var points = new [ ]
173+ // https://en.wikipedia.org/wiki/Fibonacci_number
174+ // http://stackoverflow.com/a/18121331/1182448
175+
176+ // Current Fibonacci numbers
177+ var current = 1 ;
178+ var previous = 0 ;
179+
180+ // Current bounding box
181+ var left = 0 ;
182+ var right = 1 ;
183+ var top = 0 ;
184+ var bottom = 0 ;
185+
186+ const int NumberOfRectangles = 10 ;
187+
188+ var lines = new List < Line > ( ) ;
189+ for ( var i = 0 ; i < NumberOfRectangles ; i ++ )
190+ {
191+ switch ( i % 4 )
174192 {
175- new Point ( RatioConstants . Phi5D8 , 0.0 ) , new Point ( RatioConstants . Phi5D8 , 1.0 ) ,
176- new Point ( RatioConstants . Phi5D8 , RatioConstants . Phi3D8 ) , new Point ( 1.0 , RatioConstants . Phi3D8 ) ,
193+ case 0 : // attach to bottom of current rectangle
194+ lines . AddRange ( CreateRectangle ( left , right , bottom , bottom + current ) ) ;
195+ bottom += current ;
196+ break ;
197+ case 1 : // attach to right of current rectangle
198+ lines . AddRange ( CreateRectangle ( right , right + current , top , bottom ) ) ;
199+ right += current ;
200+ break ;
201+ case 2 : // attach to top of current rectangle
202+ lines . AddRange ( CreateRectangle ( left , right , top - current , top ) ) ;
203+ top -= current ;
204+ break ;
205+ case 3 : // attach to left of current rectangle
206+ lines . AddRange ( CreateRectangle ( left - current , left , top , bottom ) ) ;
207+ left -= current ;
208+ break ;
209+ }
177210
178- // v
179- new Point ( RatioConstants . Phi5D8 + ( RatioConstants . Phi3D8 * RatioConstants . Phi3D8 ) , RatioConstants . Phi3D8 ) ,
180- new Point ( RatioConstants . Phi5D8 + ( RatioConstants . Phi3D8 * RatioConstants . Phi3D8 ) , 0.0 ) ,
211+ // Update current fibonacci number
212+ {
213+ var temp = current ;
214+ current += previous ;
215+ previous = temp ;
216+ }
217+ }
181218
182- // h
183- new Point ( RatioConstants . Phi5D8 + ( RatioConstants . Phi3D8 * RatioConstants . Phi3D8 ) , RatioConstants . Phi3D8 * RatioConstants . Phi5D8 ) ,
184- new Point ( RatioConstants . Phi5D8 , RatioConstants . Phi3D8 * RatioConstants . Phi5D8 ) ,
219+ // Scale and auto-fit (stretch all lines to 0..1 output range)
220+ var scaleX = 1.0 / ( ( double ) ( right - left ) ) ;
221+ var scaleY = 1.0 / ( ( double ) ( bottom - top ) ) ;
222+ var offsetX = left ;
223+ var offsetY = top ;
185224
186- // v
187- new Point ( RatioConstants . Phi5D8 + ( RatioConstants . Phi3D8 * RatioConstants . Phi3D8 * RatioConstants . Phi5D8 ) , RatioConstants . Phi3D8 ) ,
188- new Point ( RatioConstants . Phi5D8 + ( RatioConstants . Phi3D8 * RatioConstants . Phi3D8 * RatioConstants . Phi5D8 ) , RatioConstants . Phi3D8 * RatioConstants . Phi5D8 ) ,
189- } ;
225+ lines = lines . Select ( r => new Line (
226+ new Point ( ( r . p1 . X - offsetX ) * scaleX , ( r . p1 . Y - offsetY ) * scaleY ) ,
227+ new Point ( ( r . p2 . X - offsetX ) * scaleX , ( r . p2 . Y - offsetY ) * scaleY ) ) )
228+ . ToList ( ) ;
190229
191- return CreateLines ( points ) ;
230+ return lines ;
192231 }
193232
194- // TODO: case GridType.GoldenSpiral:
195- ////{
196- //// var res = new List<Line>();
197-
198- //// // TODO: better algorithm
199- //// var points = new List<Point>();
200- //// for (var theta = 0.0; theta < 12.0 * Math.PI; theta += 0.01 * Math.PI)
201- //// {
202- //// var r = 0.2;
203- //// r = 0.005 * Math.Pow(RatioConstants.GOLDEN_SPIRAL_C_RADIANS, theta);
204- //// var x = r * Math.Cos(theta);
205- //// var y = r * Math.Sin(theta);
206- //// points.Add(new Point(x + 0.5, y + 0.5));
207- //// }
208-
209- //// for (var i = 1; i < points.Count; i++)
233+ ////case GridType.GoldenSpiral:
210234 //// {
211- //// res.Add(new Line(new Point(points[i - 1].X, points[i - 1].Y), new Point(points[i].X, points[i].Y)));
212- //// }
235+ //// // https://en.wikipedia.org/wiki/Golden_spiral
236+ //// // http://csharphelper.com/blog/2012/05/draw-a-phi-spiral-or-golden-spiral-in-c/
213237
214- //// return res;
215- ////}
238+ //// var res = new List<Line>();
239+
240+ //// // TODO: better algorithm
241+ //// var points = new List<Point>();
242+
243+ //// for (var theta = 0.0; theta < 3.0 * 2.0 * Math.PI; theta += 0.05 * Math.PI)
244+ //// {
245+ //// var r = 0.001 * Math.Pow(RatioConstants.GoldenSpiralCInRadians, theta);
246+
247+ //// var x = 0.5 + r * Math.Cos(theta);
248+ //// var y = 0.5 + r * Math.Sin(theta);
249+ //// points.Add(new Point(x, y));
250+ //// }
251+
252+ ////const int num_slices = 1000;
253+
254+ ////var start = new Point(0, 1);
255+ ////var origin = new Point(0.5, 0.5);
256+ ////var dx = start.X - origin.X;
257+ ////var dy = start.Y - origin.Y;
258+ ////var radius = Math.Sqrt(dx * dx + dy * dy);
259+ ////var theta = Math.Atan2(dy, dx);
260+
261+ ////var dtheta = Math.PI / 2.0 / num_slices;
262+ ////var factor = 1 - (1 / RatioConstants.Phi) / num_slices * 0.78;
263+
264+ ////// Repeat until dist is too small to see.
265+ ////while (radius > 0.01)
266+ ////{
267+ //// points.Add(new Point(
268+ //// (origin.X + radius * Math.Cos(theta)),
269+ //// (origin.Y + radius * Math.Sin(theta))));
270+
271+ //// theta += dtheta;
272+ //// radius *= factor;
273+ ////}
274+
275+ //// for (var i = 1; i < points.Count; i++)
276+ //// {
277+ //// res.Add(new Line(points[i - 1], points[i]));
278+ //// }
279+
280+ //// return res;
281+ ////}
216282 default :
217283 {
218284 throw new ArgumentException ( gridType . ToString ( ) ) ;
219285 }
220286 }
221287 }
222288
289+ private static IList < Line > CreateRectangle ( int left , int right , int top , int bottom )
290+ {
291+ return new List < Line > ( new [ ]
292+ {
293+ new Line ( new Point ( left , bottom ) , new Point ( right , bottom ) ) ,
294+ new Line ( new Point ( right , bottom ) , new Point ( right , top ) ) ,
295+ new Line ( new Point ( right , top ) , new Point ( left , top ) ) ,
296+ new Line ( new Point ( left , top ) , new Point ( left , bottom ) ) ,
297+ } ) ;
298+ }
299+
223300 private static IEnumerable < Line > CreateLines ( Point [ ] points )
224301 {
225302 var res = new List < Line > ( ) ;
0 commit comments