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;
/* NOTE: "t" and "meetingPt" are in radians */
if (t > meetingPt) {
// exponential curve
r = cos(t);
if (tan(meetingPt) != 0.0) {
z = exp(cos(meetingPt) - r) / tan(meetingPt)
+ sin(meetingPt)
- 1 / tan(meetingPt);
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;
if (pContext.isPreserveZCoordinate()) {
// (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);