/*
* JAME 6.2.1
* http://jame.sourceforge.net
*
* Copyright 2001, 2016 Andrea Medeghini
*
* This file is part of JAME.
*
* JAME is an application for creating fractals and other graphics artifacts.
*
* JAME is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JAME is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with JAME. If not, see <http://www.gnu.org/licenses/>.
*
*/
package net.sf.jame.mandelbrot.renderer;
import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import net.sf.jame.core.math.Complex;
import net.sf.jame.core.util.Surface;
import net.sf.jame.mandelbrot.incolouringFormula.IncolouringFormulaRuntimeElement;
import net.sf.jame.mandelbrot.outcolouringFormula.OutcolouringFormulaRuntimeElement;
/**
* @author Andrea Medeghini
*/
public final class SimpleMandelbrotRenderer extends AbstractMandelbrotRenderer {
private final RenderingStrategy mandelbrotRenderingStrategy = new MandelbrotRenderingStrategy();
private final RenderingStrategy juliaRenderingStrategy = new JuliaRenderingStrategy();
private RendererData renderedData;
private boolean isAborted = false;
/**
* @param threadPriority
*/
public SimpleMandelbrotRenderer(final int threadPriority) {
super(threadPriority);
}
/**
* @see net.sf.jame.AbstractMandelbrotRenderer.core.fractal.renderer.AbstractFractalRenderer#free()
*/
@Override
protected void free() {
super.free();
if (renderedData != null) {
renderedData.free();
}
}
/**
* @see net.sf.jame.AbstractMandelbrotRenderer.core.fractal.renderer.AbstractFractalRenderer#init()
*/
@Override
protected void init() {
super.init();
renderedData = new RendererData();
renderedData.reallocate(getBufferWidth(), getBufferHeight());
}
/**
* @see net.sf.jame.mandelbrot.renderer.AbstractMandelbrotRenderer#doRender(boolean)
*/
@Override
protected void doRender(final boolean dynamic) {
updateShift();
updateRegion();
updateTransform();
renderingStrategy.updateParameters();
if (fractalRuntime.getRenderingFormula().getFormulaRuntime() != null) {
fractalRuntime.getRenderingFormula().getFormulaRuntime().prepareForRendering(fractalRuntime.getProcessingFormula().getFormulaRuntime(), fractalRuntime.getOrbitTrap().getOrbitTrapRuntime());
if (fractalRuntime.getOrbitTrap().getOrbitTrapRuntime() != null) {
fractalRuntime.getOrbitTrap().getOrbitTrapRuntime().prepareForProcessing(fractalRuntime.getOrbitTrap().getCenter());
}
}
for (int i = 0; i < fractalRuntime.getOutcolouringFormulaCount(); i++) {
if (fractalRuntime.getOutcolouringFormula(i).getFormulaRuntime() != null) {
if (fractalRuntime.getOutcolouringFormula(i).isAutoIterations() && (fractalRuntime.getRenderingFormula().getFormulaRuntime() != null)) {
fractalRuntime.getOutcolouringFormula(i).getFormulaRuntime().prepareForRendering(fractalRuntime.getRenderingFormula().getFormulaRuntime(), fractalRuntime.getRenderingFormula().getFormulaRuntime().getIterations());
}
else {
fractalRuntime.getOutcolouringFormula(i).getFormulaRuntime().prepareForRendering(fractalRuntime.getRenderingFormula().getFormulaRuntime(), fractalRuntime.getOutcolouringFormula(i).getIterations());
}
}
}
for (int i = 0; i < fractalRuntime.getIncolouringFormulaCount(); i++) {
if (fractalRuntime.getIncolouringFormula(i).getFormulaRuntime() != null) {
if (fractalRuntime.getIncolouringFormula(i).isAutoIterations() && (fractalRuntime.getRenderingFormula().getFormulaRuntime() != null)) {
fractalRuntime.getIncolouringFormula(i).getFormulaRuntime().prepareForRendering(fractalRuntime.getRenderingFormula().getFormulaRuntime(), fractalRuntime.getRenderingFormula().getFormulaRuntime().getIterations());
}
else {
fractalRuntime.getIncolouringFormula(i).getFormulaRuntime().prepareForRendering(fractalRuntime.getRenderingFormula().getFormulaRuntime(), fractalRuntime.getIncolouringFormula(i).getIterations());
}
}
}
final Complex px = new Complex(0, 0);
final Complex pw = new Complex(0, 0);
final RenderedPoint p = new RenderedPoint();
final double beginx = area.points[0].r;
final double endx = area.points[1].r;
final double beginy = area.points[0].i;
final double endy = area.points[1].i;
final int sizex = getBufferWidth();
final int sizey = getBufferHeight();
final double stepx = (endx - beginx) / (sizex - 1);
final double stepy = (endy - beginy) / (sizey - 1);
double posx = beginx;
double posy = beginy;
for (int x = 0; x < sizex; x++) {
renderedData.positionX[x] = posx;
posx += stepx;
}
for (int y = 0; y < sizey; y++) {
renderedData.positionY[y] = posy;
posy += stepy;
}
int offset = 0;
for (int y = 0; y < sizey; y++) {
for (int x = 0; x < sizex; x++) {
px.r = renderedData.x0;
px.i = renderedData.y0;
pw.r = renderedData.positionX[x];
pw.i = renderedData.positionY[y];
p.pr = renderedData.positionX[x];
p.pi = renderedData.positionY[y];
renderedData.newRGB[offset] = renderingStrategy.renderPoint(p, px, pw);
offset += 1;
}
if (y % 20 == 0) {
percent = (int) ((y * 100f) / sizey);
copy();
}
Thread.yield();
if (isInterrupted()) {
isAborted = true;
break;
}
}
copy();
if (isAborted) {
percent = 100;
}
}
private void copy() {
final Graphics2D g2d = getGraphics();
g2d.setComposite(AlphaComposite.Src);
g2d.drawImage(renderedData.newBuffer, 0, 0, null);
}
/**
* @see net.sf.jame.AbstractMandelbrotRenderer.core.fractal.renderer.AbstractFractalRenderer#getMandelbrotRenderingStrategy()
*/
@Override
protected RenderingStrategy getMandelbrotRenderingStrategy() {
return mandelbrotRenderingStrategy;
}
/**
* @see net.sf.jame.AbstractMandelbrotRenderer.core.fractal.renderer.AbstractFractalRenderer#createJuliaRenderingStrategy()
*/
@Override
protected RenderingStrategy getJuliaRenderingStrategy() {
return juliaRenderingStrategy;
}
/**
* @author Andrea Medeghini
*/
public static class RendererData {
/**
*
*/
public BufferedImage newBuffer;
/**
*
*/
public int[] newRGB;
/**
*
*/
public double[] positionX;
/**
*
*/
public double[] positionY;
/**
*
*/
public double x0 = 0;
/**
*
*/
public double y0 = 0;
/**
* @see java.lang.Object#finalize()
*/
@Override
public void finalize() throws Throwable {
free();
super.finalize();
}
/**
*
*/
public void free() {
positionX = null;
positionY = null;
if (newBuffer != null) {
newBuffer.flush();
}
newBuffer = null;
newRGB = null;
}
/**
* @param width
* @param height
*/
public void reallocate(final int width, final int height) {
free();
positionX = new double[width];
positionY = new double[height];
for (int i = 0; i < width; i++) {
positionX[i] = 0;
}
for (int i = 0; i < height; i++) {
positionY[i] = 0;
}
newBuffer = new BufferedImage(width, height, Surface.DEFAULT_TYPE);
newRGB = ((DataBufferInt) newBuffer.getRaster().getDataBuffer()).getData();
}
}
private class MandelbrotRenderingStrategy implements RenderingStrategy {
/**
* @see net.sf.jame.mandelbrot.renderer.AbstractMandelbrotRenderer.RenderingStrategy#isVerticalSymetrySupported()
*/
public boolean isVerticalSymetrySupported() {
for (int i = 0; i < fractalRuntime.getOutcolouringFormulaCount(); i++) {
final OutcolouringFormulaRuntimeElement outcolouringFormula = fractalRuntime.getOutcolouringFormula(i);
if ((outcolouringFormula.getFormulaRuntime() != null) && !outcolouringFormula.getFormulaRuntime().isVerticalSymetryAllowed() && outcolouringFormula.isEnabled()) {
return false;
}
}
for (int i = 0; i < fractalRuntime.getIncolouringFormulaCount(); i++) {
final IncolouringFormulaRuntimeElement incolouringFormula = fractalRuntime.getIncolouringFormula(i);
if ((incolouringFormula.getFormulaRuntime() != null) && !incolouringFormula.getFormulaRuntime().isVerticalSymetryAllowed() && incolouringFormula.isEnabled()) {
return false;
}
}
return true;
}
/**
* @see net.sf.jame.mandelbrot.renderer.AbstractMandelbrotRenderer.RenderingStrategy#isHorizontalSymetrySupported()
*/
public boolean isHorizontalSymetrySupported() {
for (int i = 0; i < fractalRuntime.getOutcolouringFormulaCount(); i++) {
final OutcolouringFormulaRuntimeElement outcolouringFormula = fractalRuntime.getOutcolouringFormula(i);
if ((outcolouringFormula.getFormulaRuntime() != null) && !outcolouringFormula.getFormulaRuntime().isHorizontalSymetryAllowed()) {
return false;
}
}
for (int i = 0; i < fractalRuntime.getIncolouringFormulaCount(); i++) {
final IncolouringFormulaRuntimeElement incolouringFormula = fractalRuntime.getIncolouringFormula(i);
if ((incolouringFormula.getFormulaRuntime() != null) && !incolouringFormula.getFormulaRuntime().isHorizontalSymetryAllowed()) {
return false;
}
}
return true;
}
/**
* @see net.sf.jame.mandelbrot.renderer.AbstractMandelbrotRenderer.RenderingStrategy#renderPoint(net.sf.jame.mandelbrot.renderer.RenderedPoint)
*/
public int renderPoint(final RenderedPoint p, final Complex px, final Complex pw) {
if ((fractalRuntime.getRenderingFormula().getFormulaRuntime() != null) && (fractalRuntime.getTransformingFormula().getFormulaRuntime() != null)) {
fractalRuntime.getTransformingFormula().getFormulaRuntime().renderPoint(pw);
p.xr = px.r;
p.xi = px.i;
p.wr = pw.r;
p.wi = pw.i;
p.dr = 0;
p.di = 0;
p.tr = 0;
p.ti = 0;
return SimpleMandelbrotRenderer.this.renderPoint(p);
}
return 0;
}
/**
* @see net.sf.jame.mandelbrot.renderer.AbstractMandelbrotRenderer.RenderingStrategy#updateParameters()
*/
public void updateParameters() {
if (fractalRuntime.getRenderingFormula().getFormulaRuntime() != null) {
renderedData.x0 = fractalRuntime.getRenderingFormula().getFormulaRuntime().getInitialPoint().r;
renderedData.y0 = fractalRuntime.getRenderingFormula().getFormulaRuntime().getInitialPoint().i;
}
else {
renderedData.x0 = 0;
renderedData.y0 = 0;
}
}
}
private class JuliaRenderingStrategy implements RenderingStrategy {
/**
* @see net.sf.jame.mandelbrot.renderer.AbstractMandelbrotRenderer.RenderingStrategy#isHorizontalSymetrySupported()
*/
public boolean isHorizontalSymetrySupported() {
return false;
}
/**
* @see net.sf.jame.mandelbrot.renderer.AbstractMandelbrotRenderer.RenderingStrategy#isVerticalSymetrySupported()
*/
public boolean isVerticalSymetrySupported() {
return false;
}
/**
* @see net.sf.jame.mandelbrot.renderer.AbstractMandelbrotRenderer.RenderingStrategy#renderPoint(net.sf.jame.mandelbrot.renderer.RenderedPoint)
*/
public int renderPoint(final RenderedPoint p, final Complex px, final Complex pw) {
if ((fractalRuntime.getRenderingFormula().getFormulaRuntime() != null) && (fractalRuntime.getTransformingFormula().getFormulaRuntime() != null)) {
fractalRuntime.getTransformingFormula().getFormulaRuntime().renderPoint(px);
p.xr = pw.r;
p.xi = pw.i;
p.wr = px.r;
p.wi = px.i;
p.dr = 0;
p.di = 0;
p.tr = 0;
p.ti = 0;
return SimpleMandelbrotRenderer.this.renderPoint(p);
}
return 0;
}
/**
* @see net.sf.jame.mandelbrot.renderer.AbstractMandelbrotRenderer.RenderingStrategy#updateParameters()
*/
public void updateParameters() {
renderedData.x0 = oldConstant.getX();
renderedData.y0 = oldConstant.getY();
}
}
}