rsidwell icon

dc_triTile

rsidwell | PRO | 10/24/17 12:47:06 AM UTC | 0 ⭐ | 1039 👁️ | Never ⏰ | []
text |

26.21 KB

|

None

|

0 👍

/

0 👎

/*
  JWildfire - an image and animation processor written in Java 
  Copyright (C) 1995-2011 Andreas Maschke
   This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 
  General Public License as published by the Free Software Foundation; either version 2.1 of the 
  License, or (at your option) any later version.
   This software 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 
  Lesser General Public License for more details.
   You should have received a copy of the GNU Lesser General Public License along with this software; 
  if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jwildfire.create.tina.variation;
  import static org.jwildfire.base.mathlib.MathLib.sin;
import static org.jwildfire.base.mathlib.MathLib.cos;
import static org.jwildfire.base.mathlib.MathLib.fmod;
import static org.jwildfire.base.mathlib.MathLib.sqr;
import static org.jwildfire.base.mathlib.MathLib.sqrt;
import static org.jwildfire.base.mathlib.MathLib.M_PI;
import static org.jwildfire.base.mathlib.MathLib.M_2PI;
 import org.jwildfire.base.Tools;
import org.jwildfire.create.tina.base.Layer;
import org.jwildfire.create.tina.base.XForm;
import org.jwildfire.create.tina.base.XYZPoint;
import org.jwildfire.create.tina.random.AbstractRandomGenerator;
 public class DCTriTileFunc extends VariationFunc {
  private static final long serialVersionUID = 1L;
   public static final double M_PHI = 1.6180339887498948482045868343656;
  public static final double M_1_PHI = 1.0 / M_PHI;
   private static final String PARAM_TILING = "type";
  private static final String PARAM_T = "t";
  private static final String PARAM_COL1 = "col1";
  private static final String PARAM_COL2 = "col2";
  private static final String PARAM_ON = "on";
  private static final String PARAM_ITT = "itt";
  private static final String PARAM_EQ = "eq";
  private static final String PARAM_DEPTH = "depth";
  private static final String PARAM_ON1 = "on1";
  private static final String PARAM_ITT1 = "itt1";
  private static final String PARAM_EQ1 = "eq1";
  private static final String PARAM_DEPTH1 = "depth1";
  private static final String PARAM_ON2 = "on2";
  private static final String PARAM_ITT2 = "itt2";
  private static final String PARAM_EQ2 = "eq2";
  private static final String PARAM_DEPTH2 = "depth2";
   private static final String[] paramNames = { PARAM_TILING, PARAM_T, PARAM_COL1, PARAM_COL2, PARAM_ON, PARAM_ITT, PARAM_EQ, PARAM_DEPTH, 
		  		PARAM_ON1, PARAM_ITT1, PARAM_EQ1, PARAM_DEPTH1, PARAM_ON2, PARAM_ITT2, PARAM_EQ2, PARAM_DEPTH2 };
   private int tiling = 1;
  private int t = 2;
  private double col1 = Math.round(Math.random() * 35 + 10) / 100.0, col2 = Math.round(Math.random() * 35 + 55) / 100.0;
  private double on = Math.round(Math.random()), on1 = Math.round(Math.random()), on2 = Math.round(Math.random());
  private int itt = (int) (Math.random() * 5 + 1), itt1 = (int) (Math.random() * 5), itt2 = (int) (Math.random() * 5);
  private int eq = (int) (Math.random() * 2 + 1), eq1 = (int) (Math.random() * 2 + 1), eq2 = (int) (Math.random() * 2 + 1);
  private int depth = (int) (Math.random() * 4), depth1 = (int) (Math.random() * 4), depth2 = (int) (Math.random() * 4);
   private double discretNoise(int x) {
	  int n = x;
	  n = (n << 13) ^ n;
	  return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff)  / (double) 0x7fffffff;
  }
   private class triangle {
	  int type;
	  double x1, y1, x2, y2, x3, y3;
	  double col;
 	  public void assign(triangle t) {
		  type = t.type; col = t.col;
		  x1 = t.x1; y1 = t.y1;
		  x2 = t.x2; y2 = t.y2;
		  x3 = t.x3; y3 = t.y3;
	  }
 	  private void blur(XYZPoint p) {
		  double u, v, v1, v2, w, x, x0, x1, x2, x3, x4, x5, x6, y, y0, y1, y2, y3, y4, y5, y6;
 		  if (this.x1 <= this.x2 && this.x1 <= this.x3) {
			  if (this.x2 <= this.x3) {
				  x1 = this.x1; y1 = this.y1;
				  x2 = this.x2; y2 = this.y2;
				  x3 = this.x3; y3 = this.y3;
			  }
			  else {
				  x1 = this.x1; y1 = this.y1;
				  x2 = this.x3; y2 = this.y3;
				  x3 = this.x2; y3 = this.y2;
			  }		  
		  }
		  else if (this.x2 <= this.x1 && this.x2 <= this.x3){
			  if (this.x1 <= this.x3) {
				  x1 = this.x2; y1 = this.y2;
				  x2 = this.x1; y2 = this.y1;
				  x3 = this.x3; y3 = this.y3;
			  }
			  else {
				  x1 = this.x2; y1 = this.y2;
				  x2 = this.x3; y2 = this.y3;
				  x3 = this.x1; y3 = this.y1;
			  }
		  }
		  else {
			  if (this.x1 <= this.x2) {
				  x1 = this.x3; y1 = this.y3;
				  x2 = this.x1; y2 = this.y1;
				  x3 = this.x2; y3 = this.y2;
			  }
			  else {
				  x1 = this.x3; y1 = this.y3;
				  x2 = this.x2; y2 = this.y2;
				  x3 = this.x1; y3 = this.y1;
			  }
		  }
 		  double r1 = genRand.random(), r2 = genRand.random();
 		  if (x1 == x2 && x2 == x3) {
			  u = x1;
			  if (y1 <= y2 && y1 <= y3) {
				  v1 = y1;
				  v2 = (y3 > y2) ? y2 : y3;
			  }
			  else if (y2 <= y1 && y2 <= y3) {
				  v1 = y2;
				  v2 = (y3 > y1) ? y1 : y3;
			  }
			  else {
				  v1 = y3;
				  v2 = (y2 > y1) ? y1 : y2;
			  }
			  v = v1 + r1 * (v2 - v1);
		  }
		  else if (x1 == x2) {
			  x4 = (x1 + x3) / 2; y4 = (y1 + y3) / 2;
			  x5 = x3 + x2 - x4; y5 = y3 + y2 - y4;
			  x6 = x1 + x2 - x4; y6 = y1 + y2 - y4;
 			  x = x3 + r1 * (x4 - x3); y = y3 + r1 * (y4 - y3);
			  x0 = x5 + r1 * (x2 - x5); y0 = y5 + r1 * (y2 - y5);
			  u = x + r2 * (x0 - x); v = y + r2 * (y0 - y);
			  w = y3 + (y2 - y3) / (x2 - x3) * (u - x3);
 			  if (y2 > y3 + (y3 - y1) / (x3 - x1) * (x2 - x3)) {
				  if (v > w) {
					  x = x4 + r1 * (x1 - x4); y = y4 + r1 * (y1 - y4);
					  x0 = x2 + r1 * (x6 - x2); y0 = y2 + r1 * (y6 - y2);
					  u = x0 + r2 * (x - x0); v = y0 + r2 * (y - y0);
				  }
			  }
			  else {
				  if (v < w) {
					  x = x4 + r1 * (x1 - x4); y = y4 + r1 * (y1 - y4);
					  x0 = x2 + r1 * (x6 - x2); y0 = y2 + r1 * (y6 - y2);
					  u = x0 + r2 * (x - x0); v = y0 + r2 * (y - y0);
				  }
			  }
		  }
		  else {
			  x4 = (x1 + x3) / 2; y4 = (y1 + y3) / 2;
			  x5 = x1 + x2 - x4; y5 = y1 + y2 - y4;
			  x6 = x3 + x2 - x4; y6 = y3 + y2 - y4;
 			  x = x1 + r1 * (x4 - x1); y = y1 + r1 * (y4 - y1);
			  x0 = x5 + r1 * (x2 - x5); y0 = y5 + r1 * (y2 - y5);
			  u = x + r2 * (x0 - x); v = y + r2 * (y0 - y);
			  w = y1 + (y2 - y1) / (x2 - x1) * (u - x1);
 			  if (y2 > y1 + (y3 - y1) / (x3 - x1) * (x2 - x1)) {
				  if (v > w) {
					  x = x4 + r1 * (x3 - x4); y = y4 + r1 * (y3 - y4);
					  x0 = x2 + r1 * (x6 - x2); y0 = y2 + r1 * (y6 - y2);
					  u = x0 + r2 * (x - x0); v = y0 + r2 * (y - y0);
				  }
			  }
			  else {
				  if (v < w) {
					  x = x4 + r1 * (x3 - x4); y = y4 + r1 * (y3 - y4);
					  x0 = x2 + r1 * (x6 - x2); y0 = y2 + r1 * (y6 - y2);
					  u = x0 + r2 * (x - x0); v = y0 + r2 * (y - y0);				  
				  }
			  }
		  }
 		  if (x1 == x2 && y1 == y2) {
			  u = x1 + r1 * (x3 - x1); v = y1 + r1 * (y3 - y1);		  
		  }
		  if (x1 == x3 && y1 == y3) {
			  u = x1 + r1 * (x2 - x1); v = y1 + r1 * (y2 - y1);
		  }
		  if (x2 == x3 && y2 == y3) {
			  u = x1 + r1 * (x2 - x1); v = y1 + r1 * (y2 - y1);
		  }
 		  p.x = u;
		  p.y = v;
		  p.z = 0;	  
	  }
  }
   private triangle orig, t1, t2;
  private XYZPoint p;
  private double alfa;
  AbstractRandomGenerator genRand;
   private void fiveFoldInit(int t, triangle orig) {
	  switch (t) {
	  case 1:
		  orig.type = 1; orig.col = col1;
		  orig.x1 = 0.0; orig.y1 = 0.0;
		  orig.x2 = cos(M_2PI/5); orig.y2 = sin(M_2PI/5);
		  orig.x3 = 2 * orig.x2; orig.y3 = 0.0;
		  break;
	  case 2:
		  orig.type = 2; orig.col = col2;
		  orig.x1 = 0.0; orig.y1 = 0.0;
		  orig.x2 = cos(M_PI/5); orig.y2 = sin(M_PI/5);
		  orig.x3 = 2 * orig.x2; orig.y3 = 0.0;
		  break;
	  }
 	  alfa = 2*cos(M_2PI/5);
  }
   private void fiveFoldDevis(triangle in, triangle out) {
	  // http://tilings.math.uni-bielefeld.de/substitution/penrose-triangle-without-rotations/
	  // (original FiveFold tiling)
	  double x4, y4, x5, y5;
	  double w;
 	  switch (in.type) {
	  case 1:
		  x4 = in.x2 + alfa * (in.x3 - in.x2); y4 = in.y2 + alfa * (in.y3 - in.y2);
 		  w = genRand.random();
 		  if (w < alfa*alfa) {
			  out.type = 1; out.col = col1;
			  out.x1 = in.x3; out.y1 = in.y3;
			  out.x2 = in.x1; out.y2 = in.y1;
			  out.x3 = x4; out.y3 = y4;
		  }
		  else {
			  out.type = 2; out.col = col2;
			  out.x1 = in.x2; out.y1 = in.y2;
			  out.x2 = x4; out.y2 = y4;
			  out.x3 = in.x1; out.y3 = in.y1;
		  }
		  break;
	  case 2:
		  x4 = in.x3 + alfa * (in.x1 - in.x3); y4 = in.y3 + alfa * (in.y1 - in.y3);
		  x5 = in.x3 + alfa * (in.x2 - in.x3); y5 = in.y3 + alfa * (in.y2 - in.y3);
 		  w = genRand.random();
 		  if (w < alfa*alfa) {
			  out.type = 2; out.col = col2;
			  out.x1 = in.x2; out.y1 = in.y2;
			  out.x2 = x4; out.y2 = y4;
			  out.x3 = in.x1; out.y3 = in.y1;
		  }
		  else if (w < 2*alfa*alfa) {
			  out.type = 2; out.col = col2;
			  out.x1 = in.x3; out.y1 = in.y3;
			  out.x2 = x5; out.y2 = y5;
			  out.x3 = x4; out.y3 = y4;
		  }
		  else {
			  out.type = 1; out.col = col1;
			  out.x1 = in.x2; out.y1 = in.y2;
			  out.x2 = x4; out.y2 = y4;
			  out.x3 = x5; out.y3 = y5;
		  }
		  break;
	  }
  }
   private void trihexInit(int t, triangle orig) {
	  switch (t) {
	  case 1:
		  orig.type = 1; orig.col = col1;
		  orig.x1 = 0.0; orig.y1 = 0.0;
		  orig.x2 = cos(M_PI/3); orig.y2 = 0.0;
		  orig.x3 = 0.0; orig.y3 = sin(M_PI/3);
		  break;
	  case 2:
		  orig.type = 2; orig.col = col2;
		  orig.x1 = 0.0; orig.y1 = 0.0;
		  orig.x2 = cos(M_PI/3); orig.y2 = 0.0;
		  orig.x3 = 0.0; orig.y3 = sin(M_PI/3);
		  break;
	  }	  
  }
   private void trihexDevis(triangle in, triangle out) {
	  // http://tilings.math.uni-bielefeld.de/substitution/trihex/
	  double x4, y4, x5, y5, x6, y6;
	  double w;
 	  x4 = (in.x1 + in.x3) / 2; y4 = (in.y1 + in.y3) / 2;
	  x5 = (in.x2 + in.x3) / 2; y5 = (in.y2 + in.y3) / 2;
	  x6 = (in.x1 + x5) / 2; y6 = (in.y1 + y5) / 2;
 	  w = genRand.random();
	  if (w < 0.25) {
		  out.type = in.type; out.col = in.type == 1 ? col1 : col2;
		  out.x1 = x4; out.y1 = y4;
		  out.x2 = x5; out.y2 = y5;
		  out.x3 = in.x3; out.y3 = in.y3;
	  }
	  else if (w < 0.5) {
		  out.type = 3 - in.type; out.col = in.type == 1 ? col2 : col1;
		  out.x1 = x4; out.y1 = y4;
		  out.x2 = x5; out.y2 = y5;
		  out.x3 = in.x1; out.y3 = in.y1;
	  }
	  else if (w < 0.75) {
		  out.type = 3 - in.type; out.col = in.type == 1 ? col2 : col1;
		  out.x1 = x6; out.y1 = y6;
		  out.x2 = x5; out.y2 = y5;
		  out.x3 = in.x2; out.y3 = in.y2;
	  }
	  else {
		  out.type = in.type; out.col = in.type == 1 ? col1 : col2;
		  out.x1 = x6; out.y1 = y6;
		  out.x2 = in.x1; out.y2 = in.y1;
		  out.x3 = in.x2; out.y3 = in.y2;
	  }
   }
   private void equiThirdsInit(int t, triangle orig) {
	  switch (t) {
	  case 1:
		  orig.type = 1; orig.col = col1;
		  orig.x1 = 0.0; orig.y1 = 0.0;
		  orig.x2 = cos(M_PI/3); orig.y2 = sin(M_PI/3);
		  orig.x3 = 2 * orig.x2; orig.y3 = 0.0;
		  break;
	  case 2:
		  orig.type = 2; orig.col = col2;
		  orig.x1 = 0.0; orig.y1 = 0.0;
		  orig.x2 = cos(M_PI/6); orig.y2 = sin(M_PI/6);
		  orig.x3 = 2 * orig.x2; orig.y3 = 0.0;
		  break;
	  }
 	  alfa = 1.0 / 3.0;
  }
   private void equiThirdsDevis(triangle in, triangle out) {
	  // http://tilings.math.uni-bielefeld.de/substitution/equithirds/
	  double x4, y4, x5, y5;
	  double w;
 	  switch (in.type) {
	  case 1:
		  x4 = in.x1 + 0.5 * (in.x3 - in.x1); y4 = in.y1 + 0.5 * (in.y3 - in.y1);
		  x5 = x4 + alfa * (in.x2 - x4); y5 = y4 + alfa * (in.y2 - y4);
 		  w = genRand.random();
 		  if (w < alfa) {
			  out.type = 2; out.col = col2;
			  out.x1 = in.x2; out.y1 = in.y2;
			  out.x2 = x5; out.y2 = y5;
			  out.x3 = in.x1; out.y3 = in.y1;
		  }
		  else if (w < 2 * alfa) {
			  out.type = 2; out.col = col2;
			  out.x1 = in.x3; out.y1 = in.y3;
			  out.x2 = x5; out.y2 = y5;
			  out.x3 = in.x2; out.y3 = in.y2;			  
		  }
		  else {
			  out.type = 2; out.col = col2;
			  out.x1 = in.x1; out.y1 = in.y1;
			  out.x2 = x5; out.y2 = y5;
			  out.x3 = in.x3; out.y3 = in.y3;
		  }
		  break;
	  case 2:
		  x4 = in.x1 + alfa * (in.x3 - in.x1); y4 = in.y1 + alfa * (in.y3 - in.y1);
		  x5 = in.x3 + alfa * (in.x1 - in.x3); y5 = in.y3 + alfa * (in.y1 - in.y3);
 		  w = genRand.random();
 		  if (w < alfa) {
			  out.type = 2; out.col = col2;
			  out.x1 = in.x2; out.y1 = in.y2;
			  out.x2 = x4; out.y2 = y4;
			  out.x3 = in.x1; out.y3 = in.y1;
		  }
		  else if (w < 2*alfa) {
			  out.type = 2; out.col = col2;
			  out.x1 = in.x3; out.y1 = in.y3;
			  out.x2 = x5; out.y2 = y5;
			  out.x3 = in.x2; out.y3 = in.y2;
		  }
		  else {
			  out.type = 1; out.col = col1;
			  out.x1 = x4; out.y1 = y4;
			  out.x2 = in.x2; out.y2 = in.y2;
			  out.x3 = x5; out.y3 = y5;
		  }
		  break;
	  }
  }
   private void ortInit(int t, triangle orig) {
	  switch (t) {
	  case 1:
		  orig.type = 1; orig.col = col1;
		  orig.x1 = 0.0; orig.y1 = 0.0;
		  orig.x2 = cos(M_2PI/5); orig.y2 = sin(M_2PI/5);
		  orig.x3 = 2 * orig.x2; orig.y3 = 0.0;
		  break;
	  case 2:
		  orig.type = 2; orig.col = col2;
		  orig.x1 = 0.0; orig.y1 = 0.0;
		  orig.x2 = cos(M_2PI/5); orig.y2 = sin(M_2PI/5);
		  orig.x3 = 2 * orig.x2; orig.y3 = 0.0;
		  break;
	  }
 	  alfa = 2*cos(M_2PI/5);
  }
   private void ortDevis(triangle in, triangle out) {
	  // http://tilings.math.uni-bielefeld.de/substitution/overlapping-robinson-triangle-1/
	  double x4, y4, x5, y5, x6, y6;
	  double w;
 	  x4 = in.x2 + alfa * (in.x1 - in.x2); y4 = in.y2 + alfa * (in.y1 - in.y2);
	  x5 = in.x1 + alfa * (in.x2 - in.x1); y5 = in.y1 + alfa * (in.y2 - in.y1);
	  x6 = in.x2 + alfa * (in.x3 - in.x2); y6 = in.y2 + alfa * (in.y3 - in.y2);
 	  w = genRand.random();
	  if (w < 0.3) {
		  out.type = 2; out.col = col2;
		  out.x1 = x4; out.y1 = y4;
		  out.x2 = in.x2; out.y2 = in.y2;
		  out.x3 = x6; out.y3 = y6;			  
	  }
	  else if (w < 0.63) {
		  out.type = 3 - in.type; out.col = in.type == 1 ? col2 : col1;
		  out.x1 = x6; out.y1 = y6;
		  out.x2 = in.x1; out.y2 = in.y1;
		  out.x3 = x5; out.y3 = y5;
	  }
	  else {
		  out.type = 1; out.col = col1;
		  out.x1 = in.x3; out.y1 = in.y3;
		  out.x2 = in.x1; out.y2 = in.y1;
		  out.x3 = x6; out.y3 = y6;
	  }
   }
   private void pinwheelInit(int t, triangle orig) {
	  switch (t) {
	  case 1:
		  orig.type = 1; orig.col = col1;
		  orig.x1 = 0.0; orig.y1 = 0.0;
		  orig.x2 = 0.0; orig.y2 = 1.0;
		  orig.x3 = 2.0; orig.y3 = 0.0;
		  break;
	  case 2:
		  orig.type = 2; orig.col = col2;
		  orig.x1 = 0.0; orig.y1 = 0.0;
		  orig.x2 = 0.0; orig.y2 = 2.0;
		  orig.x3 = 1.0; orig.y3 = 0.0;
		  break;
	  }
  }
   private void pinwheelDevis(triangle in, triangle out) {
	  // http://tilings.math.uni-bielefeld.de/substitution/pinwheel/ and https://en.wikipedia.org/wiki/Pinwheel_tiling
	  double x4, y4, x5, y5, x6, y6, x7, y7;
	  int w;
 	  switch(in.type) {
	  case 1:
		  x4 = in.x2 + 0.2 * (in.x3 - in.x2); y4 = in.y2 + 0.2 * (in.y3 - in.y2);
		  x5 = in.x2 + 0.6 * (in.x3 - in.x2); y5 = in.y2 + 0.6 * (in.y3 - in.y2);
		  x6 = in.x1 + 0.5 * (in.x3 - in.x1); y6 = in.y1 + 0.5 * (in.y3 - in.y1);
		  x7 = in.x1 + 0.5 * (x4 - in.x1); y7 = in.y1 + 0.5 * (y4 - in.y1);
 		  w = (int) (genRand.random() * 5);
		  switch (w) {
		  case 0:
			  out.type = 2; out.col = col2;
			  out.x1 = x4; out.y1 = y4;
			  out.x2 = in.x1; out.y2 = in.y1;
			  out.x3 = in.x2; out.y3 = in.y2;
			  break;
		  case 1:
			  out.type = 2; out.col = col2;
			  out.x1 = x7; out.y1 = y7;
			  out.x2 = x6; out.y2 = y6;
			  out.x3 = in.x1; out.y3 = in.y1;
			  break;
		  case 2:
			  out.type = 1; out.col = col1;
			  out.x1 = x7; out.y1 = y7;
			  out.x2 = x4; out.y2 = y4;
			  out.x3 = x6; out.y3 = y6;
			  break;
		  case 3:
			  out.type = 1; out.col = col1;
			  out.x1 = x5; out.y1 = y5;
			  out.x2 = x6; out.y2 = y6;
			  out.x3 = x4; out.y3 = y4;
			  break;
		  case 4:
			  out.type = 2; out.col = col2;
			  out.x1 = x5; out.y1 = y5;
			  out.x2 = in.x3; out.y2 = in.y3;
			  out.x3 = x6; out.y3 = y6;
			  break;
		  }
		  break;
	  case 2:
		  x4 = in.x3 + 0.2 * (in.x2 - in.x3); y4 = in.y3 + 0.2 * (in.y2 - in.y3);
		  x5 = in.x3 + 0.6 * (in.x2 - in.x3); y5 = in.y3 + 0.6 * (in.y2 - in.y3);
		  x6 = in.x1 + 0.5 * (in.x2 - in.x1); y6 = in.y1 + 0.5 * (in.y2 - in.y1);
		  x7 = in.x1 + 0.5 * (x4 - in.x1); y7 = in.y1 + 0.5 * (y4 - in.y1);
 		  w = (int) (genRand.random() * 5);
		  switch (w) {
		  case 0:
			  out.type = 1; out.col = col1;
			  out.x1 = x4; out.y1 = y4;
			  out.x2 = in.x3; out.y2 = in.y3;
			  out.x3 = in.x1; out.y3 = in.y1;
			  break;
		  case 1:
			  out.type = 1; out.col = col1;
			  out.x1 = x7; out.y1 = y7;
			  out.x2 = in.x1; out.y2 = in.y1;
			  out.x3 = x6; out.y3 = y6;
			  break;
		  case 2:
			  out.type = 2; out.col = col2;
			  out.x1 = x7; out.y1 = y7;
			  out.x2 = x6; out.y2 = y6;
			  out.x3 = x4; out.y3 = y4;
			  break;
		  case 3:
			  out.type = 2; out.col = col2;
			  out.x1 = x5; out.y1 = y5;
			  out.x2 = x4; out.y2 = y4;
			  out.x3 = x6; out.y3 = y6;
			  break;
		  case 4:
			  out.type = 1; out.col = col1;
			  out.x1 = x5; out.y1 = y5;
			  out.x2 = x6; out.y2 = y6;
			  out.x3 = in.x2; out.y3 = in.y2;
			  break;
		  }
		  break;
	  }
  }
   private void goldInit(int t, triangle orig) {
	  switch (t) {
	  case 1:
		  orig.type = 1; orig.col = col1;
		  orig.x1 = 0.0; orig.y1 = 0.0;
		  orig.x2 = M_1_PHI; orig.y2 = sqrt(M_1_PHI);
		  orig.x3 = orig.x2; orig.y3 = 0.0;
		  break;
	  case 2:
		  orig.type = 2; orig.col = col2;
		  orig.x1 = 0.0; orig.y1 = 0.0;
		  orig.x2 = 0.0; orig.y2 = sqrt(M_1_PHI);
		  orig.x3 = 1.0; orig.y3 = 0.0;
		  break;
	  }
 	  alfa = sqr(M_1_PHI);
  }
   private void goldDevis(triangle in, triangle out) {
	  // http://tilings.math.uni-bielefeld.de/substitution/golden-pinwheel/
	  double x4, y4, x5, y5, x6, y6, x7, y7, x8, y8, x9, y9, x10, y10;
	  double w;
 	  switch(in.type) {
	  case 1:
		  x4 = in.x1 + alfa * (in.x2 - in.x1); y4 = in.y1 + alfa * (in.y2 - in.y1);
		  x5 = in.x2 + alfa * (in.x1 - in.x2); y5 = in.y2 + alfa * (in.y1 - in.y2);
		  x6 = in.x3 + alfa * (in.x2 - in.x3); y6 = in.y3 + alfa * (in.y2 - in.y3);
		  x7 = in.x1 + alfa * (in.x3 - in.x1); y7 = in.y1 + alfa * (in.y3 - in.y1);
 		  w = genRand.random();
		  if (w < 0.146) {
			  out.type = 1; out.col = col1;
			  out.x1 = in.x1; out.y1 = in.y1;
			  out.x2 = x4; out.y2 = y4;
			  out.x3 = x7; out.y3 = y7;			  
		  }
		  else if (w < 0.382) {
			  out.type = 2; out.col = col2;
			  out.x1 = x4; out.y1 = y4;
			  out.x2 = x7; out.y2 = y7;
			  out.x3 = x6; out.y3 = y6;			  
		  }
		  else if (w < 0.618) {
			  out.type = 2; out.col = col2;
			  out.x1 = in.x3; out.y1 = in.y3;
			  out.x2 = x6; out.y2 = y6;
			  out.x3 = x7; out.y3 = y7;
		  }
		  else if (w < 0.764) {
			  out.type = 1; out.col = col1;
			  out.x1 = x4; out.y1 = y4;
			  out.x2 = x6; out.y2 = y6;
			  out.x3 = x5; out.y3 = y5;			  
		  }
		  else {
			  out.type = 2; out.col = col2;
			  out.x1 = x5; out.y1 = y5;
			  out.x2 = x6; out.y2 = y6;
			  out.x3 = in.x2; out.y3 = in.y2;			  
		  }
		  break;
	  case 2:
		  x4 = in.x2 + alfa * (in.x1 - in.x2); y4 = in.y2 + alfa * (in.y1 - in.y2);
		  x5 = in.x2 + alfa * (in.x3 - in.x2); y5 = in.y2 + alfa * (in.y3 - in.y2);
		  x6 = in.x3 + alfa * (in.x2 - in.x3); y6 = in.y3 + alfa * (in.y2 - in.y3);
		  x7 = in.x1 + alfa * (in.x3 - in.x1); y7 = in.y1 + alfa * (in.y3 - in.y1);
		  x8 = in.x3 + alfa * (in.x1 - in.x3); y8 = in.y3 + alfa * (in.y1 - in.y3);
		  x9 = x4 + alfa * (x7 - x4); y9 = y4 + alfa * (y7 - y4);
		  x10 = x7 + alfa * (x4 - x7); y10 = y7 + alfa * (y4 - y7);
 		  w = genRand.random();
		  if (w < 0.146) {
			  out.type = 2; out.col = col2;
			  out.x1 = x4; out.y1 = y4;
			  out.x2 = in.x2; out.y2 = in.y2;
			  out.x3 = x5; out.y3 = y5;			  
		  }
		  else if (w < 0.236) {
			  out.type = 1; out.col = col1;
			  out.x1 = x4; out.y1 = y4;
			  out.x2 = x5; out.y2 = y5;
			  out.x3 = x9; out.y3 = y9;			  
		  }
		  else if (w < 0.382) {
			  out.type = 2; out.col = col2;
			  out.x1 = x10; out.y1 = y10;
			  out.x2 = in.x1; out.y2 = in.y1;
			  out.x3 = x4; out.y3 = y4;			  
		  }
		  else if (w < 0.472) {
			  out.type = 1; out.col = col1;
			  out.x1 = x7; out.y1 = y7;
			  out.x2 = in.x1; out.y2 = in.y1;
			  out.x3 = x10; out.y3 = y10;			  
		  }
		  else if (w < 0.618) {
			  out.type = 2; out.col = col2;
			  out.x1 = x9; out.y1 = y9;
			  out.x2 = x5; out.y2 = y5;
			  out.x3 = x7; out.y3 = y7;			  
		  }
		  else if (w < 0.764) {
			  out.type = 2; out.col = col2;
			  out.x1 = x6; out.y1 = y6;
			  out.x2 = x5; out.y2 = y5;
			  out.x3 = x7; out.y3 = y7;			  
		  }
		  else if (w < 0.854) {
			  out.type = 1; out.col = col1;
			  out.x1 = x7; out.y1 = y7;
			  out.x2 = x6; out.y2 = y6;
			  out.x3 = x8; out.y3 = y8;			  
		  }
		  else {
			  out.type = 2; out.col = col2;
			  out.x1 = x8; out.y1 = y8;
			  out.x2 = x6; out.y2 = y6;
			  out.x3 = in.x3; out.y3 = in.y3;			  
		  }
		  break;
	  }
  }
   private void devis(triangle t1, triangle t2) {
	  switch (tiling) {
	  case 1:
		  fiveFoldDevis(t1,t2);
		  break;
	  case 2:
		  trihexDevis(t1,t2);
		  break;
	  case 3:
		  equiThirdsDevis(t1,t2);
		  break;
	  case 4:
		  ortDevis(t1,t2);
		  break;
	  case 5:
		  pinwheelDevis(t1,t2);
		  break;
	  case 6:
		  goldDevis(t1,t2);
		  break;
	  }
  }
   @Override
  public void init(FlameTransformationContext pContext, Layer pLayer, XForm pXForm, double pAmount) {
	  orig = new triangle();
 	  switch (tiling) {
	  case 1:
		  fiveFoldInit(t, orig);
		  break;
	  case 2:
		  trihexInit(t, orig);
		  break;
	  case 3:
		  equiThirdsInit(t, orig);
		  break;
	  case 4:
		  ortInit(t, orig);
		  break;
	  case 5:
		  pinwheelInit(t, orig);
		  break;
	  case 6:
		  goldInit(t, orig);
		  break;
	  }
 	  genRand = pContext.getRandGen();
	  t1 = new triangle();
	  t2 = new triangle();
	  p = new XYZPoint();
  }
   @Override
  public void transform(FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount) {
    /* extension of FiveFold by eralex61, https://eralex61.deviantart.com/art/Five-fold-example-of-finite-recurent-system-in-Apo-705813367 */
 	  t1.assign(orig); t1.col = 0.25;
	  t2.assign(orig); t2.col = 0.0;
 	  int n = itt;
	  int k = 1;
 	  while (n > 0) {
		  devis(t1, t2);
		  t1.assign(t2);
 		  if (on < 0.5) {
			  if ((k == itt) && (t1.type != eq)) n = n + depth;
		  }
		  else {
			  if ((k >= itt) && (k < itt + depth) && (t1.type != eq)) n = n + 1;
		  }
		  n = n - 1;
		  k = k + 1;
	  }
 	  int m = 0;
	  switch (t1.type) {
	  case 1:
		  n = itt1;
		  k = 1;
		  while (n > 0) {
			  devis(t1, t2);
			  t1.assign(t2);
			  m = 2 * m + t2.type - 1;
			  if (on1 < 0.5) {
				  if ((k == itt1) && (t1.type != eq1)) n = n + depth1;
			  }
			  else {
				  if ((k >= itt1) && (k < itt1 + depth1) && (t1.type != eq1)) n = n + 1;
			  }
			  n = n - 1;
			  k = k + 1;
		  }
		  t1.col = discretNoise(m+43);
		  break;
	  case 2:
		  n = itt2;
		  k = 1;
		  while (n > 0) {
			  devis(t1, t2);
			  t1.assign(t2);
			  m = 2 * m + t2.type - 1;
			  if (on2 < 0.5) {
				  if ((k == itt2) && (t1.type != eq2)) n = n + depth2;
			  }
			  else {
				  if ((k >= itt2) && (k < itt2 + depth2) && (t1.type != eq2)) n = n + 1;
			  }
			  n = n - 1;
			  k = k + 1;
		  }
		  t1.col = discretNoise(m+31);
		  break;
	  }
 	  t2.blur(p);
 	  pVarTP.x += pAmount * p.x;
	  pVarTP.y += pAmount * p.y;
	  pVarTP.z += pAmount * p.z;
	  pVarTP.color = fmod(t1.col + t2.col, 1.0);
   }
   @Override
  public String[] getParameterNames() {
    return paramNames;
  }
   @Override
  public Object[] getParameterValues() {
    return new Object[] { tiling, t, col1, col2, on, itt, eq, depth, on1, itt1, eq1, depth1, on2, itt2, eq2, depth2 };
  }
   @Override
  public String[] getParameterAlternativeNames() {
     return new String[] { "FiveFold_Tiling", "FiveFold_T", "FiveFold_Col1", "FiveFold_Col2", "FiveFold_On", "FiveFold_Itt", "FiveFold_Eq", "FiveFold_Depth", "FiveFold_On1", "FiveFold_Itt1", "FiveFold_Eq1", "FiveFold_Depth1", "FiveFold_On2", "FiveFold_Itt2", "FiveFold_Eq2", "FiveFold_Depth2" };
   }
   @Override
  public void setParameter(String pName, double pValue) {
    if (PARAM_TILING.equalsIgnoreCase(pName))
        tiling = Tools.FTOI(pValue);
    else if (PARAM_T.equalsIgnoreCase(pName))
        t = Tools.FTOI(pValue);
    else if (PARAM_COL1.equalsIgnoreCase(pName))
        col1 = pValue;
    else if (PARAM_COL2.equalsIgnoreCase(pName))
        col2 = pValue;
    else if (PARAM_ON.equalsIgnoreCase(pName))
        on = pValue;
    else if (PARAM_ITT.equalsIgnoreCase(pName))
        itt = Tools.FTOI(pValue);
    else if (PARAM_EQ.equalsIgnoreCase(pName))
        eq = Tools.FTOI(pValue);
    else if (PARAM_DEPTH.equalsIgnoreCase(pName))
        depth = Tools.FTOI(pValue);
    else if (PARAM_ON1.equalsIgnoreCase(pName))
        on1 = pValue;
    else if (PARAM_ITT1.equalsIgnoreCase(pName))
        itt1 = Tools.FTOI(pValue);
    else if (PARAM_EQ1.equalsIgnoreCase(pName))
        eq1 = Tools.FTOI(pValue);
    else if (PARAM_DEPTH1.equalsIgnoreCase(pName))
        depth1 = Tools.FTOI(pValue);
    else if (PARAM_ON2.equalsIgnoreCase(pName))
        on2 = pValue;
    else if (PARAM_ITT2.equalsIgnoreCase(pName))
        itt2 = Tools.FTOI(pValue);
    else if (PARAM_EQ2.equalsIgnoreCase(pName))
        eq2 = Tools.FTOI(pValue);
    else if (PARAM_DEPTH2.equalsIgnoreCase(pName))
        depth2 = Tools.FTOI(pValue);
    else
      throw new IllegalArgumentException(pName);
  }
   @Override
  public String getName() {
    return "dc_triTile";
  }
 }

Comments