use of org.jwildfire.create.tina.base.XYZPoint in project JWildfire by thargor6.
the class HexesFunc method transform.
@Override
public void transform(FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount) {
double[][] P = new double[VORONOI_MAXPOINTS][2];
double DXo, DYo, L, L1, L2, R, s, trgL, Vx, Vy;
double[] U = new double[2];
int Hx, Hy;
// For speed/convenience
s = this.cellsize;
// Infinite number of small cells? No effect . . .
if (0.0 == s) {
return;
}
// Get cartesian co-ordinates, and convert to hex co-ordinates
U[_x_] = pAffineTP.x;
U[_y_] = pAffineTP.y;
Hx = (int) floor((a_hex * U[_x_] + b_hex * U[_y_]) / s);
Hy = (int) floor((c_hex * U[_x_] + d_hex * U[_y_]) / s);
// Get a set of 9 hex centre points, based around the one above
int i = 0;
int di, dj;
for (di = -1; di < 2; di++) {
for (dj = -1; dj < 2; dj++) {
cell_centre(Hx + di, Hy + dj, s, P[i]);
i++;
}
}
int q = closest(P, 9, U);
// Remake list starting from chosen hex, ensure it is completely surrounded (total 7 points)
// First adjust centres according to which one was found to be closest
Hx += cell_choice[q][_x_];
Hy += cell_choice[q][_y_];
// First point is central/closest
cell_centre(Hx, Hy, cellsize, P[0]);
// In hex co-ords, offsets are: (0,1) (1,1) (1,0) (0,-1) (-1,-1) (-1, 0)
cell_centre(Hx, Hy + 1, s, P[1]);
cell_centre(Hx + 1, Hy + 1, s, P[2]);
cell_centre(Hx + 1, Hy, s, P[3]);
cell_centre(Hx, Hy - 1, s, P[4]);
cell_centre(Hx - 1, Hy - 1, s, P[5]);
cell_centre(Hx - 1, Hy, s, P[6]);
L1 = voronoi(P, 7, 0, U);
// Delta vector from centre of hex
DXo = U[_x_] - P[0][_x_];
DYo = U[_y_] - P[0][_y_];
// ///////////////////////////////////////////////////////////////
// Apply "interesting bit" to cell's DXo and DYo co-ordinates
// trgL is the defined value of l, independent of any rotation
trgL = pow(L1 + 1e-100, power) * scale;
// Rotate
Vx = DXo * rotCos + DYo * rotSin;
Vy = -DXo * rotSin + DYo * rotCos;
// ////////////////////////////////////////////////////////////////
// Measure voronoi distance again
U[_x_] = Vx + P[0][_x_];
U[_y_] = Vy + P[0][_y_];
L2 = voronoi(P, 7, 0, U);
// ////////////////////////////////////////////////////////////////
// Scale to meet target size . . . adjust according to how close
// we are to the edge
// Code here attempts to remove the "rosette" effect caused by
// scaling difference between corners and closer edges
// L is maximum of L1 or L2 . . .
// When L = 0.8 or higher . . . match trgL/L2 exactly
// When L = 0.5 or less . . . match trgL/L1 exactly
L = (L1 > L2) ? L1 : L2;
if (L < 0.5) {
R = trgL / L1;
} else {
if (L > 0.8) {
R = trgL / L2;
} else {
R = ((trgL / L1) * (0.8 - L) + (trgL / L2) * (L - 0.5)) / 0.3;
}
}
Vx *= R;
Vy *= R;
// Add cell centre co-ordinates back in
Vx += P[0][_x_];
Vy += P[0][_y_];
// Finally add values in
applyCellCalculation(pVarTP, pAmount, L, Vx, Vy);
}
use of org.jwildfire.create.tina.base.XYZPoint in project JWildfire by thargor6.
the class JuliaScopeFunc method transformFunction.
public void transformFunction(FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount) {
int rnd = pContext.random(absPower);
double a;
if ((rnd & 1) == 0)
a = (2 * M_PI * rnd + atan2(pAffineTP.y, pAffineTP.x)) / power;
else
a = (2 * M_PI * rnd - atan2(pAffineTP.y, pAffineTP.x)) / power;
double sina = sin(a);
double cosa = cos(a);
double r = pAmount * pow(sqr(pAffineTP.x) + sqr(pAffineTP.y), cPower);
pVarTP.x = pVarTP.x + r * cosa;
pVarTP.y = pVarTP.y + r * sina;
if (pContext.isPreserveZCoordinate()) {
pVarTP.z += pAmount * pAffineTP.z;
}
}
use of org.jwildfire.create.tina.base.XYZPoint in project JWildfire by thargor6.
the class KleinGroupFunc method transform.
@Override
public void transform(FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount) {
// if avoid_reversals is false,
// randomly pick one of the four calculated Mobius transformation matrices, a, b, A, B where A = inverse(a), B = inverse(b)
//
// if avoid_reversals is true trying to give the variation some internal "memory"
// for a first pass, remember last used matrix (out of a, b, A, B)
// and use that to choose different sets of matrices to randomly sample from
// for example to avoid getting successive pairs of matrix m and inverse M, which
// would cancel each other out: m(z)M(z) = z
// so selecting randomly each time from the set of transforms that won't cause a reversal
Complex[][] mtransforms;
// (aA, bB, Aa, Bb)
if (avoid_reversal) {
if (prev_matrix == mat_a) {
mtransforms = not_A;
} else if (prev_matrix == mat_inv_a) {
mtransforms = not_a;
} else if (prev_matrix == mat_b) {
mtransforms = not_B;
} else if (prev_matrix == mat_inv_b) {
mtransforms = not_b;
} else // shouldn't get here...
{
mtransforms = all_matrices;
}
} else {
mtransforms = all_matrices;
}
// randomly select a matrix from the list of matrices
int mindex = pContext.random(mtransforms.length);
Complex[] mat = mtransforms[mindex];
// then use selected matrix for Mobius transformation:
// f(z) = (az + b) / (cz + d);
// for the generator matrices
// [0, 1, 2, 3] = [a, b, c, d] ==> f(z)= (az+b)/(cz+d)
//
double xin = pAffineTP.x;
double yin = pAffineTP.y;
xin /= pAmount;
yin /= pAmount;
Complex win = new Complex(xin, yin);
Complex a = mat[0];
Complex b = mat[1];
Complex c = mat[2];
Complex d = mat[3];
Complex wout = win.mul(a).add(b).div(win.mul(c).add(d));
pVarTP.x += pAmount * wout.re();
pVarTP.y += pAmount * wout.im();
if (pContext.isPreserveZCoordinate()) {
pVarTP.z += pAmount * pAffineTP.z;
}
prev_matrix = mat;
}
use of org.jwildfire.create.tina.base.XYZPoint in project JWildfire by thargor6.
the class Onion2Func method transform.
@Override
public void transform(FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount) {
/* Description:
The transform creates a shape similar to an onion by starting with a circle
and smoothly transitioning to a (negative) exponential function. In this case,
they meet where exp(x) has a slope of 1.
To make the function spherical, the point's x and y values are treated as a
radius and become "t". The circle and exponential function are then formed
from parametric equations, where "t" is the same "t" from the original point's
x and y values.
These equations are as follows:
circle: xp=cos(t), yp=sin(t) (or r=cos(t), z=sin(t))
exponential: xp=cos(t), yp=exp(s) (or r=cos(t), z=exp(s))
where "s" represents a shifted "t" value so as to aline the exponential
function with the circle.
The slope of the circle:
dyp/dxp = cos(t)dt/-sin(t)dt = -cot(t)
Thus, cot(t) becomes the coefficient on exp(x) so as to make the slopes the
same. However, this requires a y-axis realignment of cot(t) instead of 1
in addition to a shift in the y-axis to bring exp(t) to meet with the circle.
y-axis-shift = sin(t) - cot(t)
This value of "t" - where the circle and exponential function meet - is
called "m", and it is a user-set variable.
Thus, the shifts for exp(s) are:
x-axis shift = cos(m)
y-axis shift = sin(m) - cot(m)
Final exponential equation:
xp = cos(t)
yp = cot(t)*exp( -xp + cos(m) ) + sin(m) - cot(m)
NOTE: xp is made negative instead of cot(t) so as to perform the desired
mirror in parametric space.
*/
// Initial coordinates
XYZPoint ini = new XYZPoint();
ini.x = pAffineTP.x;
ini.y = pAffineTP.y;
ini.z = pAffineTP.z;
ini.x -= shift_x;
ini.y -= shift_y;
// ini.z -= shift_z;
ini.invalidate();
// Final coordinates in parametric space
double r;
double z;
/* Convert x and y of point to parametric space,
noting they are the radius outward in real space. */
double t = ini.getPrecalcSqrt() / stretch - M_PI / 2;
if (t > meeting_pt) {
// exponential curve
r = cos(t);
if (tan(meeting_pt) != 0.0) {
z = exp(cos(meeting_pt) - r) / tan(meeting_pt) + sin(meeting_pt) - 1 / tan(meeting_pt);
if (z > top_crop && top_crop > 0) {
/* FIX ADDED. top_crop could start at -1 for cropping below middle. */
z = top_crop;
r = 0;
}
} else {
z = top_crop;
}
} else {
// circular curve
r = cos(t);
z = sin(t);
}
// Expand radius of onion
r *= circle_a * pAmount;
z *= circle_b * pAmount;
// Convert parametric space (2D) back to real space (3D)
/* A new coordinate equals the new factor times a unit vector in the
direction of the coordinate of interest. */
pVarTP.x += r * (ini.x / ini.getPrecalcSqrt());
pVarTP.y += r * (ini.y / ini.getPrecalcSqrt());
pVarTP.z += z;
{
// (this should cause positive z values to curl inside the onion)
/* Treating z as a vector that is split into two components, one being
an x-component of parametric space which becomes a new radius for
real space, taking into account conversion through unit vectors */
pVarTP.x += r * ini.z * (ini.x / ini.getPrecalcSqrt());
pVarTP.y += r * ini.z * (ini.y / ini.getPrecalcSqrt());
/* The z-component is a normalized value from the parametric space y
(which is real space z), taking into account the amount that went into
the x component. */
pVarTP.z += ini.z * z / (r * r + z * z);
}
pVarTP.x += shift_x;
pVarTP.y += shift_y;
// pVarTP.z += shift_z;
}
use of org.jwildfire.create.tina.base.XYZPoint in project JWildfire by thargor6.
the class Julia3DZFunc method transformFunction.
public void transformFunction(FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount) {
double r2d = pAffineTP.x * pAffineTP.x + pAffineTP.y * pAffineTP.y;
double r = pAmount * pow(r2d, cPower);
int rnd = (int) (pContext.random() * absPower);
double angle = (atan2(pAffineTP.y, pAffineTP.x) + 2 * M_PI * rnd) / power;
double sina = sin(angle);
double cosa = cos(angle);
pVarTP.x += r * cosa;
pVarTP.y += r * sina;
pVarTP.z += r * pAffineTP.z / (sqrt(r2d) * absPower);
}
Aggregations