/* This file is part of the source code for 3D-XplorMath-J, Version 1.0 (January 2008).
* Copyright (c) 2008 The 3D-XplorMath Consortium (http://3d-xplormath.org).
* This source code is released under a BSD License, which allows redistribution
* in source and binary form, with or without modification, provided copyright
* and license information are included, and with no warranty or guarantee of
* any kind. For details, see http://3d-xplormath.org/j/source/BSDLicense.txt
*/
package vmm3d.planecurve.parametric;
import vmm3d.core.Parameter;
import vmm3d.core.UserExhibit;
import vmm3d.core.VariableParamAnimateable;
/**
* A plane curve c(s) = (x(s),y(s)) is defined by its curvature function kappa(s).
* kappa(s) is to be entered by the user.
* The Frenet equation c''(s) = kappa(s)*normal(s) gives c'(s) = (cos(alpha(s)), sin(alpha(s)) ),
* where alpha'(s) = kappa(s). Therefore c(s) is obtained by a double integration.
* We use a precomputed antiderivative alphs of kappa, stored in helpArray. This reduces the
* double integration to a single one - and this is fast enough so that these Frenet curves
* behave as if they were given by an explicit parametrization.
* If tmin =< 0 =< tmax then alpha(0) = 0.
*/
public class UserPlaneCurveParametricKappa extends PlaneCurveParametric implements UserExhibit {
private UserExhibit.Support userExhibitSupport;
private UserExhibit.FunctionInfo kappa;
double[] helpArray = new double[513];
boolean needsNewHelpArray;
double DT,Tstart;
public UserPlaneCurveParametricKappa() {
tmin.reset(-10);
tmax.reset(+10);
tResolution.reset(257);
userExhibitSupport = new UserExhibit.Support(this);
userExhibitSupport.addFunctionParameter(new VariableParamAnimateable("a",1.0,1.0,1.0));
userExhibitSupport.addFunctionParameter(new VariableParamAnimateable("b",1.0,0.5,1));
kappa = userExhibitSupport.addRealFunction("kappa", "b *(2+cos(a*t))", "t");
setDefaultWindow(-2,2,-2,2);
needsNewHelpArray = true;
DT = (tmax.getValue()-tmin.getValue())/(helpArray.length-1);
Tstart = Math.max(Math.min(0, tmax.getValue()), tmin.getValue());
}
public void parameterChanged(Parameter param, Object oldValue, Object newValue) {
super.parameterChanged(param, oldValue, newValue);
needsNewHelpArray = true;
Tstart = Math.max(Math.min(0, tmax.getValue()), tmin.getValue());
}
public double xValue(double t) {
long num = 2*Math.round(2+4*Math.abs(t-Tstart));
double x = 0;
double f = Math.cos(angle(Tstart));
if ((t-Tstart) != 0){
x = x + f;
double dt = (t-Tstart)/num;
for (int i = 1; i < num; i=i+2){
f = Math.cos(angle(Tstart+i*dt));
x = x + 4*f;
f = Math.cos(angle(Tstart+(i+1)*dt));
x = x + 2*f;
}
x = (x - f)*dt/3;
}
return x ;
}
public double yValue(double t) {
long num = 2*Math.round(2+4*Math.abs(t-Tstart));
double y = 0;
double f = Math.sin(angle(Tstart));
if ((t-Tstart) != 0){
y = y + f;
double dt = (t-Tstart)/num;
for (int i = 1; i < num; i=i+2)
{
y = y + 4*Math.sin(angle(Tstart+i*dt));
f = Math.sin(angle(Tstart+(i+1)*dt));
y = y + 2*f;
}
y = (y - f)*dt/3;
}
return y ;
}
public double xDerivativeValue(double t) {
return Math.cos(angle(t));
}
public double yDerivativeValue(double t) {
return Math.sin(angle(t));
}
public double x2ndDerivativeValue(double t) {
return -Math.sin(angle(t))*kappa.realFunctionValue(t);
}
public double y2ndDerivativeValue(double t) {
return Math.cos(angle(t))*kappa.realFunctionValue(t);
}
public Support getUserExhibitSupport() {
return userExhibitSupport;
}
private void recomputeHelpArray(){
int num = 4;
double tm = tmin.getValue();
DT = (tmax.getValue()-tm)/(helpArray.length-1);
double w;
double f = 0;
double dt = DT/num;
helpArray[0] = 0;
for (int j = 1; j < helpArray.length; j++){
w = kappa.realFunctionValue(tm);
for (int i = 1; i < num; i=i+2){
w = w + 4*kappa.realFunctionValue(tm+i*dt);
f = kappa.realFunctionValue(tm+(i+1)*dt);
w = w + 2*f;
}
w = (w - f)*dt/3;
tm = tm + DT;
helpArray[j] = helpArray[j-1] + w;
}
needsNewHelpArray = false;
double an = angle(Tstart);
for (int j = 0; j < helpArray.length; j++){
helpArray[j] = helpArray[j] - an;
}
}
/**
* Simpson integration (1 4 2 4 2 ...2 4 1) of integrand = kappa(s)
*/
private double angle(double t) {
if (needsNewHelpArray)
{ recomputeHelpArray(); }
double w = 0; double y = 0; double dt;
int k = (int) Math.max(0, Math.min(Math.round((t-tmin.getValue())/DT), helpArray.length-1) );
double ta = tmin.getValue() + k*DT;
if (t == ta ) { w = helpArray[k];}
else
{
int num = (int) (2*Math.round(2 + 8*Math.abs(t-ta)));
dt = (t-ta)/num;
w = w + kappa.realFunctionValue(ta);
for (int i = 1; i < num; i=i+2){
w = w + 4*kappa.realFunctionValue(ta+i*dt);
y = kappa.realFunctionValue(ta+(i+1)*dt);
w = w + 2*y;
}
w = helpArray[k] + (w - y)*dt/3;
}
return w;
}
/* private double angle(double t) { // same function as before, without helper array
long num = 2*Math.round(2+4*Math.abs(t));
double w = 0;
if (t != 0){
double y = kappa.realFunctionValue(0);
double dt = t/num;
w = w + y;
for (int i = 1; i < num; i=i+2){
y = kappa.realFunctionValue(i*dt);
w = w + 4*y;
y = kappa.realFunctionValue((i+1)*dt);
w = w + 2*y;
}
w = (w - y)*dt/3;
}
return w;
}*/
}
Ads help maintain this website.