Title: Iterated Function Systems Post by: Crucifixio on August 29, 2008, 01:21:11 AM Hello everybody,
This this my first time I'm writing on this forum, I've got problem which I can't manage myself, namly I'm writing program about Iterated Function System in which user can set parameters for transformation (contraction) - create his own fractals, generate them and calculate Minkowski dimension. The problem I'm fighting with is how to check affine transformation for contraction (arbitrary) - I don't know which metric to use. My contraction transformation looks like |a b| |e| |c d| + |f | plus one parameter for probability. BTW. If there any solution to automatic set probablity to contraction function to work ?? Any help would be very helpfull. Title: Re: Iterated Function Systems Post by: cKleinhuis on August 29, 2008, 09:52:22 AM hello there, you can use the determinant of the matrix to check if it is contractous or not, if i understood you right ... :dink:
Title: Re: Iterated Function Systems Post by: David Makin on August 29, 2008, 10:36:11 AM If you mean "How do I calculate the probababilities from the scales ?" then the answer is given by:
log(p0)/log(s0)=log(p1)/log(s1)=log(p2)/log(s2)=....=log(pn)/log(sn)=constant and p0+p1+p2+p3+...+pn = 1 The above lead to: P0+P0^(log(S1)/log(S0))+P0^(log(S2)/log(S0))+....+P0^(log(Sn)/log(S0))=1.0 where p1 to pn are the probabilities and s1 to sn are the scales. This only works provided that all scales are contractive and non-zero - and obviously all transforms are purely affine. Also "constant" in the above gives the fractal dimension. Title: Re: Iterated Function Systems Post by: Crucifixio on August 29, 2008, 12:26:41 PM Trifox - simple matrix determinant check will tell me that this transformation is contraction ?? If Det > 0 than it's contraction.
Title: Re: Iterated Function Systems Post by: Crucifixio on August 29, 2008, 12:29:49 PM David Makin,
In your formula scales s0...sn are which parameters of transformation matrix ?? Title: Re: Iterated Function Systems Post by: cKleinhuis on August 29, 2008, 01:24:52 PM the determinant gives you the scale change of the transformation
1= no change 0 = object is scaled to zero -1 = object is mirrored around center 0.5 = object is scaled halve remember that you only take the 2x2 part of the 2x3 matrix, the translation part has no affect on the scale :D |a b| |e| |c d| + |f | Title: Re: Iterated Function Systems Post by: David Makin on August 29, 2008, 06:02:30 PM The s0 to sn are the scales, normally the values of the 2*2 determinant for 2D fractals or the 3*3 determinant for 3D fractals.
As Trifox stated you get contraction when abs(determinant) is >0 and <1. Title: Re: Iterated Function Systems Post by: David Makin on August 29, 2008, 06:08:56 PM I should add:
1. Use the absolute scales. 2. that you can solve: P0+P0^(log(S1)/log(S0))+P0^(log(S2)/log(S0))+....+P0^(log(Sn)/log(S0))=1.0 using a binary search if you take s0 as the largest scale. Title: Re: Iterated Function Systems Post by: Crucifixio on August 29, 2008, 08:18:21 PM Thanks very much guys, when I finish I will post my program on to this forum.
Title: Re: Iterated Function Systems Post by: cKleinhuis on August 29, 2008, 09:38:51 PM Thanks very much guys, when I finish I will post my program on to this forum. i do hope so ! O0 O0 O0 Title: Re: Iterated Function Systems Post by: Crucifixio on August 30, 2008, 12:26:56 PM One more question log function is log10 or logn
Title: Re: Iterated Function Systems Post by: David Makin on August 31, 2008, 08:17:15 PM Because the calculation involves log(a)/log(b) it doesn't matter what the log base is as long as you use the same base for log(a) as log(b) :)
Title: Re: Iterated Function Systems Post by: Ross Hilbert on September 04, 2008, 08:34:13 PM Here is what I use. Start from the bottom and work up.
Hope this helps. Ross ' ' Define Affine object. ' Object Affine { A : B : C : D : E : F } ' ' Normalize the count values in weights[]. ' On return, the values will all be between 0 and 1 ' and the sum of all values will equal 1. ' void Math.NormalizeWeights(weights[], count) { sum = 0 for (idx = 0, idx < count, idx += 1) { sum += weights[idx] } for (idx = 0, idx < count, idx += 1) { weights[idx] /= sum } } ' ' Return the determinate of an affine transformation matrix. ' Complex Affine.Determinate(Affine a) = a.A*a.D - a.B*a.C ' ' Affine.TransformPoint applies an affine transformation ' matrix to a point z and returns the resulting point. ' ' A B E z.X A*z.X + B*z.Y + E ' C D F * z.Y = C*z.X + D*z.Y + F ' 0 0 1 1 1 ' Complex Affine.TransformPoint(Affine a, z) { return Complex( \ a.A*z.x + a.B*z.y + a.E, \ a.C*z.x + a.D*z.y + a.F \ ) } ' ' Generate a random contraction map. ' ' To be a contraction map, the affine transformation ' coefficients must satisfy the following conditions: ' ' a^2 + c^2 < 1 ' b^2 + d^2 < 1 ' a^2 + b^2 + c^2 + d^2 < 1 + (a*d - c*b)^2 ' Affine Affine.RandomContractionMap(center, radius) { while (True) { a = Random.NumberInRange(-1, 1) w = Sqrt(1 - a^2) c = Random.NumberInRange(-w, w) b = Random.NumberInRange(-1, 1) w = Sqrt(1 - b^2) d = Random.NumberInRange(-w, w) if (a^2 + b^2 + c^2 + d^2 < 1 + (a*d - c*b)^2) { break } } e = center.x + Random.NumberInRange(-radius, radius) f = center.y + Random.NumberInRange(-radius, radius) return Affine(a, b, c, d, e, f) } ' ' Initialize weights w[] using the weighted average of ' the absolute value of the determinates of the affine ' transformations in s[]. ' ' For a discussion of the following algorithm, see: ' "Chaos and Fractals" ' by Peitgen, Jurgens, Saupe, Section 6.3 pages 327-329. ' void Affine.InitializeWeights(Affine s[], w[], count) { for (idx = 0, idx < count, idx += 1) { w[idx] = Max(0.01, Abs(Affine.Determinate(s[idx]))) } Math.NormalizeWeights(w[], count) } ' ' N is the number of Affine transformations. ' s[N] are the Affine transformations. ' w[N] are the weights. ' Complex w[N] Affine s[N] for (idx = 0, idx < N, idx += 1) { s[idx] = Affine.RandomContractionMap(0, 1) } Affine.InitializeWeights(s[], w[], N) Title: Re: Iterated Function Systems Post by: David Makin on September 04, 2008, 09:07:20 PM Hi,
Just to say that using the "log(Pi)/log(Si)=constant" method provides more accurate results than the method from "Chaos and Fractals" (I verified this by using both methods for the probablilities on many fractals and found that when the scales are not uniform this method was noticeably better at filling the gaps evenly). The proof of the method can be found in: "A Multifractal Analysis of IFSP Invariant Measures With Application to Fractal Image Generation" by J.M.Gutiérrez, A.Iglesias and M.A. Rodríguez. The document was formerly available on the web as fractals96.pdf Title: Re: Iterated Function Systems Post by: Ross Hilbert on September 04, 2008, 10:56:49 PM Thanks David,
I found the document you referenced and I'll give it a read. Looks good, thanks again! Ross Title: Re: Iterated Function Systems Post by: Ross Hilbert on September 05, 2008, 02:53:17 PM David,
Yep, the "log(Pi)/log(Si)=constant" method provides more accurate results than the method from "Chaos and Fractals"! One small problem, if the set of affine transformations includes a transformation with scale=1 (e.g., a rotation), the algorithm fails since the log(Si)=0. In that case, do you simply use a method like that from "Chaos and Fractals" or is there a better solution? Ross Title: Re: Iterated Function Systems Post by: cKleinhuis on September 05, 2008, 03:33:17 PM you can now use tex for formatting formulas:
Title: Re: Iterated Function Systems Post by: David Makin on September 05, 2008, 04:20:52 PM You are correct, the method only works for scales >0 and <1.
If you have scales of "1" for a "whole" transform included as part of the IFS then I don't really know how you're getting a convergent fractal :) Having said that you can either use the Barnsley/"Chaos and Fractals" method instead or maybe use say 0.99 as the scale instead of 1 or (and I think I did this) first normalise the scales so the sum of them is 1 then apply the log(Pi)/log(Si)=constant method using the normalised scales as Si. One thing to mention is that in log(Pi)/log(Si)=constant the constant is the fractal dimension if you use the linear scales. If using the scales directly from the determinants then the constant is dimension/2 for 2D fractals and dimension/3 for 3D fractals. Title: Re: Iterated Function Systems Post by: Ross Hilbert on September 05, 2008, 05:34:20 PM Thanks David,
As to your question: If you have scales of "1" for a "whole" transform included as part of the IFS then I don't really know how you're getting a convergent fractal... See http://classes.yale.edu/Fractals/IntroToFrac/InvProb/SnowIFS/Snow2.html for an example. They state: "The Random Algorithm still will generate the snowflake, so long as on average the transformations applied are contractions." Just using 0.99 gives results that are far worse than using the Barnsley/"Chaos and Fractals" method. I tried your suggestion of normalizing the scales first and that works fine. Thanks for your clarification with respect to the relationship of the constant (in log(Pi)/log(Si)=constant) and the fractal dimension, but just to be clear, this is not relevent with respect to the algorithm to calculate the probabilities from the scales, right? Ross Title: Re: Iterated Function Systems Post by: Ross Hilbert on September 05, 2008, 09:17:27 PM For completeness, here is the updated code using the reference David suggested.
Ross Code: ' Title: Re: Iterated Function Systems Post by: David Makin on September 05, 2008, 09:23:34 PM "See http://classes.yale.edu/Fractals/IntroToFrac/InvProb/SnowIFS/Snow2.html for an example. They state: "The Random Algorithm still will generate the snowflake, so long as on average the transformations applied are contractions.""
Yea - I remember now, the chaos game will still work, as will the deterministic method if you include the "artificial" termination of the IFS tree at a given maximum depth in addition to terminating at a given overall scale :) With respect to the relevance of the fractal dimension, it's relevant in that it's the constant involved and in the fact that you can use log(Pi)/log(Si)=constant to generate a fractal based on the original so that it has a particular dimension but the same "form" as the original. e.g. I use: if @fixdim gs = fd/@dim gi = ft repeat gt = tfs[gi] tfs[gi] = tfs[gi]^gs gt = tfs[gi]/gt tf0[gi] = tf0[gi]*gt tf1[gi] = tf1[gi]*gt tf2[gi] = tf2[gi]*gt tf3[gi] = tf3[gi]*gt until (gi=gi-1)<0 fd = @dim endif Where: fd is the original calculated dimension @dim is the requested dimension ft is "first transform" number (usually number of transforms-1) gi is the loop transform number tfs[] are the scales tf0[] to tf3[] are the 2*2 transformation matrix values. This method is based on keeping the same probabilities. Title: Re: Iterated Function Systems Post by: Ross Hilbert on September 05, 2008, 09:50:54 PM Cool, I learned a lot. Thanks.
Title: Re: Iterated Function Systems Post by: David Makin on September 05, 2008, 09:59:55 PM Just to add one other thing with respect to generating IFS fractals using the chaos game method - you probably know anyway - the statistical randomness of the pseudo-random you use is almost as important as getting the probabilities "correct" - the default C++/Windows rand() is *terrible*.
I did quite a lot of searching on this and found that the best pseudo-random generator is one called the "Mersenne Twister", I've lost my links but you should be able to find code for it. Title: Re: Iterated Function Systems Post by: David Makin on September 05, 2008, 10:50:00 PM e.g. I use: if @fixdim gs = fd/@dim gi = ft repeat gt = tfs[gi] tfs[gi] = tfs[gi]^gs gt = tfs[gi]/gt tf0[gi] = tf0[gi]*gt tf1[gi] = tf1[gi]*gt tf2[gi] = tf2[gi]*gt tf3[gi] = tf3[gi]*gt until (gi=gi-1)<0 fd = @dim endif Where: fd is the original calculated dimension @dim is the requested dimension ft is "first transform" number (usually number of transforms-1) gi is the loop transform number tfs[] are the scales tf0[] to tf3[] are the 2*2 transformation matrix values. This method is based on keeping the same probabilities. Sorry - important to mention that in the above the scales used are the linear scales i.e. sqrt(abs(determinant)). (Use cuberoot(abs(determinant)) for 3D). Title: Re: Iterated Function Systems Post by: David Makin on September 05, 2008, 11:39:06 PM Note that using the chaos game method to render IFS then the fractal dimension is important for when making your program as "black box" as possible.
I mean that if you render a fractal at one size with a given iteration count for the chaos game method and then wish to render it at say a much larger size then the required iteration count for "the same" image is based on the fractal dimension and ideally your program should be able to automatically adjust the actual iteration count used accordingly. Normally you'd use something like: count = (userparam*sqrt(pixelwidth*pixelheight))^fractaldimension Title: Re: Iterated Function Systems Post by: Ross Hilbert on September 06, 2008, 06:22:14 PM Great information David, thanks again.
Ross Title: Re: Iterated Function Systems Post by: David Makin on May 12, 2009, 01:49:10 PM Note that using the chaos game method to render IFS then the fractal dimension is important for when making your program as "black box" as possible. I mean that if you render a fractal at one size with a given iteration count for the chaos game method and then wish to render it at say a much larger size then the required iteration count for "the same" image is based on the fractal dimension and ideally your program should be able to automatically adjust the actual iteration count used accordingly. Normally you'd use something like: count = (userparam*sqrt(pixelwidth*pixelheight))^fractaldimension Just to add that the above works best when the whole fractal is on-screen, if not then the accuracy will depend on how the density of the fractal varies across it's area and which area of the fractal is in view. |