Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/arranger/jarl/widget/filter/Fractal.java


1   package com.arranger.jarl.widget.filter;
2   
3   import com.arranger.jarl.base.IContext;
4   import com.arranger.jarl.base.IGradientManager;
5   import com.arranger.jarl.base.IJarlObjectInfo;
6   import com.arranger.jarl.util.InterpolateUtil;
7   import com.arranger.jarl.util.ObjectUtil;
8   import com.arranger.jarl.util.WidgetConfigSegment;
9   import com.arranger.jarl.util.JarlInfoUtil;
10  import com.jhlabs.image.Gradient;
11  import org.w3c.dom.Element;
12  
13  import java.awt.*;
14  import java.awt.geom.Point2D;
15  
16  /**
17   * Fractal creates a mandelbrot fractal.  note, this currently will ignore
18   * traits, strokes & filters...
19   *
20   * @widgetAttribute gradientIndex ## xs:integer ## the gradient index
21   * @widgetAttribute iterations ## xs:integer ## the max number of iterations
22   * @widgetAttribute complexRect ## xs:string ## the complex rectangle to show
23   *
24   * @widgetAttribute startGradientIndex ## xs:integer ## the starting gradient index
25   * @widgetAttribute startIterations ## xs:integer ## the starting max number of iterations
26   * @widgetAttribute startComplexRect ## xs:string ## the starting complex rectangle to show
27   * @widgetAttribute endGradientIndex ## xs:integer ## the ending gradient index
28   * @widgetAttribute endIterations ## xs:integer ## the ending max number of iterations
29   * @widgetAttribute endComplexRect ## xs:string ## the ending complex rectangle to show
30   */
31  public class Fractal extends BaseFilterWidget {
32  
33      protected static final int NUM_COLORS = 512;
34  
35      protected int m_gradientIndex = Integer.MAX_VALUE;
36      protected int m_iterations = Integer.MAX_VALUE;
37      protected ComplexRect m_complexRect;
38  
39      protected int m_startGradientIndex = Integer.MAX_VALUE;
40      protected int m_endGradientIndex = Integer.MAX_VALUE;
41      protected int m_startIterations = Integer.MAX_VALUE;
42      protected int m_endIterations = Integer.MAX_VALUE;
43      protected ComplexRect m_startComplexRect;
44      protected ComplexRect m_endComplexRect;
45  
46  
47      protected void _paint(IContext context, Graphics2D graphics2D) {
48          //calc real width & height
49          double width = getWidth(context);
50          double height = getHeight(context);
51  
52          //get & fixup complex rect
53          ComplexRect complexRect = null;
54          if (m_complexRect != null) {
55              complexRect = m_complexRect;
56          } else if (m_startComplexRect != null && m_endComplexRect != null) {
57  
58              //interpolate
59              double realMin = InterpolateUtil.interpolate(m_startTime,
60                      m_endTime,
61                      m_startComplexRect.m_realMin,
62                      m_endComplexRect.m_realMin,
63                      context.getTime());
64  
65              double realMax = InterpolateUtil.interpolate(m_startTime,
66                      m_endTime,
67                      m_startComplexRect.m_realMax,
68                      m_endComplexRect.m_realMax,
69                      context.getTime());
70  
71              double imagMin = InterpolateUtil.interpolate(m_startTime,
72                      m_endTime,
73                      m_startComplexRect.m_imagMin,
74                      m_endComplexRect.m_imagMin,
75                      context.getTime());
76  
77              double imagMax = InterpolateUtil.interpolate(m_startTime,
78                      m_endTime,
79                      m_startComplexRect.m_imagMax,
80                      m_endComplexRect.m_imagMax,
81                      context.getTime());
82              complexRect = new ComplexRect(realMin, realMax, imagMin, imagMax);
83          } else {
84              FractalConfigSegment fractalConfigSegment = (FractalConfigSegment) getCurrentSegment(context);
85              double currentTimePct = getCurrentSegmentTimePct(context, fractalConfigSegment);
86  
87              ComplexRect startComplexRect = fractalConfigSegment.getStartComplexRect();
88              ComplexRect endComplexRect = fractalConfigSegment.getEndComplexRect();
89  
90              double realMin = InterpolateUtil.interpolate(0,
91                      1,
92                      startComplexRect.m_realMin,
93                      endComplexRect.m_realMin,
94                      currentTimePct);
95  
96              double realMax = InterpolateUtil.interpolate(0,
97                      1,
98                      startComplexRect.m_realMax,
99                      endComplexRect.m_realMax,
100                     currentTimePct);
101 
102             double imagMin = InterpolateUtil.interpolate(0,
103                     1,
104                     startComplexRect.m_imagMin,
105                     endComplexRect.m_imagMin,
106                     currentTimePct);
107 
108             double imagMax = InterpolateUtil.interpolate(0,
109                     1,
110                     startComplexRect.m_imagMax,
111                     endComplexRect.m_imagMax,
112                     currentTimePct);
113             complexRect = new ComplexRect(realMin, realMax, imagMin, imagMax);
114         }
115 
116 
117         complexRect = ComplexRect.adjust(complexRect, width, height);
118 
119         //get the color map from the gradient (try caching?)
120         Color[] colors = prepareColorArray(context);
121 
122         //iterations
123         int iterations = 0;
124         if (m_iterations != Integer.MAX_VALUE) {
125             iterations = m_iterations;
126         } else if (m_startIterations != Integer.MAX_VALUE && m_endIterations != Integer.MAX_VALUE) {
127             iterations = (int) InterpolateUtil.interpolate(m_startTime,
128                     m_endTime,
129                     m_startIterations,
130                     m_endIterations,
131                     context.getTime());
132         } else {
133             FractalConfigSegment fractalConfigSegment = (FractalConfigSegment) getCurrentSegment(context);
134             double currentTimePct = getCurrentSegmentTimePct(context, fractalConfigSegment);
135 
136             iterations = (int) InterpolateUtil.interpolate(0,
137                     1,
138                     fractalConfigSegment.getStartIterations(),
139                     fractalConfigSegment.getEndIterations(),
140                     currentTimePct);
141         }
142 
143         //for each pixel get the color
144         Color color = graphics2D.getColor();
145         paintFractal(width, height, iterations, complexRect, graphics2D, colors, context);
146         graphics2D.setColor(color);
147     }
148 
149     protected void paintFractal(double width, double height, int maxIterations, ComplexRect complexRect, Graphics2D graphics2D, Color[] colors, IContext context) {
150         double delta = (complexRect.m_realMax - complexRect.m_realMin) / width;
151 
152         Point2D centerPoint = new Point2D.Double(context.getWidth() / 2.0, context.getHeight() / 2.0);
153         int offsetX = (int) (centerPoint.getX() - (width / 2.0));
154         int offsetY = (int) (centerPoint.getY() - (height / 2.0));
155 
156         for (int x = 0; x < width; x++) {
157             for (int y = 0; y < height; y++) {
158                 Color color = getColorForPoint(x, y, delta, height, maxIterations, complexRect, colors);
159                 graphics2D.setColor(color);
160                 graphics2D.drawLine(x + offsetX, y + offsetY, x + offsetX, y + offsetY);
161             }
162         }
163     }
164 
165     protected Color getColorForPoint(double x, double y, double delta, double height, int maxIterations, ComplexRect complexRect, Color[] colors) {
166         Color c = Color.black;
167         double zR = complexRect.m_realMin + x * delta;
168         double zI = complexRect.m_imagMin + ((height - y)) * delta;
169 
170         // Is the point inside the set?
171         int numIterations = testPoint(zR, zI, maxIterations);
172 
173         if (numIterations != 0) {
174             // The point is outside the set. It gets a color based on the number
175             // of iterations it took to know this.
176             int colorNum = (int) ((float) colors.length * (1.0 -
177                     (float) numIterations / (float) maxIterations));
178             colorNum = (colorNum == colors.length) ? 0 : colorNum;
179 
180             c = colors[colorNum];
181         }
182         return c;
183     }
184 
185     /**
186      * Is the given complex point, (cR, cI), in the Mandelbrot set?
187      * Use the formula: z <= z*z + c, where z is initially equal to c.
188      * If |z| >= 2, then the point is not in the set.
189      * Return 0 if the point is in the set; else return the number of
190      * iterations it took to decide that the point is not in the set.
191      */
192     protected int testPoint(double cR, double cI, int maxIterations) {
193         double zR = cR;
194         double zI = cI;
195 
196         for (int i = 1; i <= maxIterations; i++) {
197             // To square a complex number: (a+bi)(a+bi) = a*a - b*b + 2abi
198             double zROld = zR;
199             zR = zR * zR - zI * zI + cR;
200             zI = 2 * zROld * zI + cI;
201 
202             // We know that if the distance from z to the origin is >= 2
203             // then the point is out of the set.  To avoid a square root,
204             // we'll instead check if the distance squared >= 4.
205             double distSquared = zR * zR + zI * zI;
206             if (distSquared >= 4) {
207                 return i;
208             }
209         }
210         return 0;
211     }
212 
213     /**
214      * Get the gradient color map
215      */
216     protected Color[] prepareColorArray(IContext context) {
217 
218         IGradientManager gradientManager = context.getGradientManager();
219 
220         Gradient gradient;
221         if (m_gradientIndex != Integer.MAX_VALUE) {
222             gradient = gradientManager.getGradient(m_gradientIndex);
223         } else if (m_startGradientIndex != Integer.MAX_VALUE && m_endGradientIndex != Integer.MAX_VALUE) {
224             //interpolate
225             double currentTimePct = InterpolateUtil.interpolate(this, context.getTime());
226             Gradient gradient1 = gradientManager.getGradient(m_startGradientIndex);
227             Gradient gradient2 = gradientManager.getGradient(m_endGradientIndex);
228             gradient = gradientManager.interpolate(gradient1, gradient2, currentTimePct);
229 
230         } else {
231             FractalConfigSegment fractalConfigSegment = (FractalConfigSegment) getCurrentSegment(context);
232             double currentTimePct = getCurrentSegmentTimePct(context, fractalConfigSegment);
233 
234             //interpolate
235             Gradient gradient1 = gradientManager.getGradient(fractalConfigSegment.getStartGradientIndex());
236             Gradient gradient2 = gradientManager.getGradient(fractalConfigSegment.getEndGradientIndex());
237             gradient = gradientManager.interpolate(gradient1, gradient2, currentTimePct);
238         }
239 
240         Color[] colorMap = new Color[NUM_COLORS];
241         for (int colorNum = 0; colorNum < NUM_COLORS; colorNum++) {
242             float f = (float) colorNum / (float) NUM_COLORS;
243             int color = gradient.getColor(f);
244             colorMap[colorNum] = new Color(color);
245         }
246 
247         return colorMap;
248     }
249 
250     protected void initAttributes(IContext context) {
251         super.initAttributes(context);
252 
253         ObjectUtil.initializeField("gradientIndex", m_configElement, this, ObjectUtil.PRIMITIVE_CONVERSION);
254         ObjectUtil.initializeField("iterations", m_configElement, this, ObjectUtil.PRIMITIVE_CONVERSION);
255         ObjectUtil.initializeField("complexRect", m_configElement, this, ComplexRect.COMPLEX_CONVERSION);
256 
257         ObjectUtil.initializeField("startGradientIndex", m_configElement, this, ObjectUtil.PRIMITIVE_CONVERSION);
258         ObjectUtil.initializeField("startIterations", m_configElement, this, ObjectUtil.PRIMITIVE_CONVERSION);
259         ObjectUtil.initializeField("startComplexRect", m_configElement, this, ComplexRect.COMPLEX_CONVERSION);
260         ObjectUtil.initializeField("endGradientIndex", m_configElement, this, ObjectUtil.PRIMITIVE_CONVERSION);
261         ObjectUtil.initializeField("endIterations", m_configElement, this, ObjectUtil.PRIMITIVE_CONVERSION);
262         ObjectUtil.initializeField("endComplexRect", m_configElement, this, ComplexRect.COMPLEX_CONVERSION);
263     }
264 
265     protected void addJarlObjectInfo(IJarlObjectInfo jarlObjectInfo) {
266         super.addJarlObjectInfo(jarlObjectInfo);
267         populateInfo(jarlObjectInfo, "gradientIndex", "Gradient Index", JarlInfoUtil.PRIMITIVE_DISPLAY);
268         populateInfo(jarlObjectInfo, "iterations", "Iterations", JarlInfoUtil.PRIMITIVE_DISPLAY);
269         populateInfo(jarlObjectInfo, "complexRect", "Complex Rect", ComplexRect.COMPLEX_DISPLAY);
270 
271         populateInfo(jarlObjectInfo, "startGradientIndex", "Start Gradient Index", JarlInfoUtil.PRIMITIVE_DISPLAY);
272         populateInfo(jarlObjectInfo, "endGradientIndex", "End Gradient Index", JarlInfoUtil.PRIMITIVE_DISPLAY);
273         populateInfo(jarlObjectInfo, "startIterations", "Start Iterations", JarlInfoUtil.PRIMITIVE_DISPLAY);
274         populateInfo(jarlObjectInfo, "endIterations", "End Iterations", JarlInfoUtil.PRIMITIVE_DISPLAY);
275         populateInfo(jarlObjectInfo, "startComplexRect", "Start Complex Rect", ComplexRect.COMPLEX_DISPLAY);
276         populateInfo(jarlObjectInfo, "endComplexRect", "End Complex Rect", ComplexRect.COMPLEX_DISPLAY);
277     }
278 
279     public WidgetConfigSegment createSegment(Element element) {
280         return new FractalConfigSegment(element);
281     }
282 
283     public static class FractalConfigSegment extends WidgetConfigSegment {
284 
285         protected int m_startGradientIndex = Integer.MAX_VALUE;
286         protected int m_endGradientIndex = Integer.MAX_VALUE;
287         protected int m_startIterations = Integer.MAX_VALUE;
288         protected int m_endIterations = Integer.MAX_VALUE;
289         protected ComplexRect m_startComplexRect;
290         protected ComplexRect m_endComplexRect;
291 
292 
293         public FractalConfigSegment(Element element) {
294             super(element);
295 
296             ObjectUtil.initializeFieldStrict("startGradientIndex", element, this, ObjectUtil.PRIMITIVE_CONVERSION);
297             ObjectUtil.initializeFieldStrict("startIterations", element, this, ObjectUtil.PRIMITIVE_CONVERSION);
298             ObjectUtil.initializeFieldStrict("startComplexRect", element, this, ComplexRect.COMPLEX_CONVERSION);
299             ObjectUtil.initializeFieldStrict("endGradientIndex", element, this, ObjectUtil.PRIMITIVE_CONVERSION);
300             ObjectUtil.initializeFieldStrict("endIterations", element, this, ObjectUtil.PRIMITIVE_CONVERSION);
301             ObjectUtil.initializeFieldStrict("endComplexRect", element, this, ComplexRect.COMPLEX_CONVERSION);
302         }
303 
304         protected void addJarlObjectInfo(IJarlObjectInfo jarlObjectInfo) {
305             super.addJarlObjectInfo(jarlObjectInfo);
306             populateInfo(jarlObjectInfo, "startGradientIndex", "Start Gradient Index", JarlInfoUtil.PRIMITIVE_DISPLAY);
307             populateInfo(jarlObjectInfo, "endGradientIndex", "End Gradient Index", JarlInfoUtil.PRIMITIVE_DISPLAY);
308             populateInfo(jarlObjectInfo, "startIterations", "Start Iterations", JarlInfoUtil.PRIMITIVE_DISPLAY);
309             populateInfo(jarlObjectInfo, "endIterations", "End Iterations", JarlInfoUtil.PRIMITIVE_DISPLAY);
310             populateInfo(jarlObjectInfo, "startComplexRect", "Start Complex Rect", ComplexRect.COMPLEX_DISPLAY);
311             populateInfo(jarlObjectInfo, "endComplexRect", "End Complex Rect", ComplexRect.COMPLEX_DISPLAY);
312         }
313 
314         public int getStartGradientIndex() {
315             return m_startGradientIndex;
316         }
317 
318         public int getEndGradientIndex() {
319             return m_endGradientIndex;
320         }
321 
322         public int getStartIterations() {
323             return m_startIterations;
324         }
325 
326         public int getEndIterations() {
327             return m_endIterations;
328         }
329 
330         public ComplexRect getStartComplexRect() {
331             return m_startComplexRect;
332         }
333 
334         public ComplexRect getEndComplexRect() {
335             return m_endComplexRect;
336         }
337     }
338 }