00001 /** 00002 * @file RFunction.h 00003 * Common base class for unions and intersections; both are defined using 00004 * R-Functions, with only a difference in sign in one of the terms. 00005 * 00006 * @author Steve Zelinka 00007 */ 00008 00009 #ifndef _RFUNCTION_H 00010 #define _RFUNCTION_H 00011 00012 #include "Blend.h" 00013 00014 /** 00015 * A subclass of blending that implements R-functions for CSG. 00016 * R-functions are blending functions that apply CSG operations 00017 * to implicit surfaces. The benefit of R-functions are that they 00018 * smooth the field surrounding the zero-surfaces to eliminate 00019 * the creasing that can result from, say, min and max functions. 00020 */ 00021 class RFunction : public Blend 00022 { 00023 protected: 00024 /** 00025 * The continuity to be provided. 00026 * This is stored as a double to avoid integer 00027 * round-offs later. 00028 */ 00029 double m_cont; 00030 00031 /** 00032 * The sign of the second-half of the RFunction. 00033 * This differentiates 00034 * a union (= -1) from an intersection (= 1). 00035 * @note The sign is opposite of that used in the 00036 * original R-function paper where f<0 outside. 00037 */ 00038 int m_sign; 00039 00040 /** 00041 * Evaluates the R-function on the two function values. 00042 * 00043 * @param f The value of f. 00044 * @param g The value of g. 00045 * @return (f + g + m_sign*(sqrt(f^2+g^2)))*(f^2+g^2)^(m_cont/2). 00046 */ 00047 virtual double h(double f, double g); 00048 virtual Intervald h(Intervald f, Intervald g); 00049 00050 /** 00051 * Evaluates the partial derivative with respect to f 00052 * on the two function values. 00053 * 00054 * h = (f + g + m_sign*(sqrt(f^2+g^2)))*(f^2+g^2)^(m_cont/2). 00055 * hf = (f^2+g^2)^(m_cont/2)*d(f + g + m_sign*(sqrt(f^2+g^2)))/df + 00056 * (f + g + m_sign*(sqrt(f^2+g^2)))*d(f^2+g^2)^(m_cont/2)/df 00057 * = (f^2+g^2)^(m_cont/2)*(1 + m_sign*f/sqrt(f^2+g^2)) + 00058 * (f + g + m_sign*(sqrt(f^2+g^2)))*m_cont*f*(f^2+g^2)^(m_cont/2 - 1). 00059 * 00060 * @param f The value of f. 00061 * @param g The value of g. 00062 * @return hf. 00063 * 00064 * \note Appears to work fine when tested with particles. 00065 */ 00066 virtual double hf(double f, double g); 00067 virtual Intervald hf(Intervald f, Intervald g); 00068 00069 /** 00070 * Evaluates the partial derivative with respect to g 00071 * on the two function values. 00072 * 00073 * h = (f + g + m_sign*(sqrt(f^2+g^2)))*(f^2+g^2)^(m_cont/2). 00074 * hg = (f^2+g^2)^(m_cont/2)*d(f + g + m_sign*(sqrt(f^2+g^2)))/dg + 00075 * (f + g + m_sign*(sqrt(f^2+g^2)))*d(f^2+g^2)^(m_cont/2)/dg 00076 * = (f^2+g^2)^(m_cont/2)*(1 + m_sign*g/sqrt(f^2+g^2)) + 00077 * (f + g + m_sign*(sqrt(f^2+g^2)))*m_cont*g*(f^2+g^2)^(m_cont/2 - 1). 00078 * 00079 * @param f The value of f. 00080 * @param g The value of g. 00081 * @return hg. 00082 * 00083 * \note Appears to work fine when tested with particles. 00084 */ 00085 virtual double hg(double f, double g); 00086 virtual Intervald hg(Intervald f, Intervald g); 00087 00088 /** 00089 * Evaluates the 2nd partial derivative with respect to f 00090 * and f on the two function values. 00091 * 00092 * fg = sqrt(f^2 + g^2) 00093 * dfg/df = f/fg 00094 * hf = fg^m_cont*(1 + m_sign*f/fg) + 00095 * (f + g + m_sign*fg)*m_cont*f*fg^(m_cont - 2) 00096 * = fg^m_cont + m_sign*f*fg^(m_cont-1) + 00097 * (f + g + m_sign*fg)*m_cont*f*fg^(m_cont - 2) 00098 * hff = m_cont*fg^(m_cont-1)*dfg/df + 00099 * m_sign*f*(m_cont-1)*fg^(m_cont-2)*dfg/df + 00100 * m_sign*fg^(m_cont-1) + 00101 * (1 + m_sign*dfg/df)*m_cont*f*fg^(m_cont - 2) + 00102 * (f + g + m_sign*fg)*m_cont*(f*(m_cont - 2)*fg^(m_cont - 3)*dfg/df + 00103 * fg^(m_cont - 2)) 00104 * = m_cont*f*fg^(m_cont-2) + 00105 * m_sign*(m_cont-1)*f^2*fg^(m_cont-3) + 00106 * m_sign*fg^(m_cont-1) + 00107 * m_cont*f*fg^(m_cont - 2) + m_cont*m_sign*f^2*fg^(m_cont - 3) + 00108 * m_cont*(f + g + m_sign*fg)*((m_cont - 2)*f^2*fg^(m_cont - 4) + 00109 * fg^(m_cont - 2)) 00110 * 00111 * @param f The value of f. 00112 * @param g The value of g. 00113 * @return hff. 00114 * 00115 * \note Needs to be tested. 00116 */ 00117 virtual double hff(double f, double g); 00118 virtual Intervald hff(Intervald f, Intervald g); 00119 00120 /** 00121 * Evaluate the 2nd partial derivative with respect to f 00122 * and g on the two function values. 00123 * 00124 * fg = sqrt(f^2 + g^2) 00125 * dfg/dg = g/fg 00126 * hf = fg^m_cont*(1 + m_sign*f/fg) + 00127 * (f + g + m_sign*fg)*m_cont*f*fg^(m_cont - 2) 00128 * = fg^m_cont + m_sign*f*fg^(m_cont-1) + 00129 * (f + g + m_sign*fg)*m_cont*f*fg^(m_cont - 2) 00130 * hfg = m_cont*fg^(m_cont-1)*dfg/dg + 00131 * m_sign*f*(m_cont-1)*fg^(m_cont-2)*dfg/dg + 00132 * m_sign*fg^(m_cont-1) + 00133 * (1 + m_sign*dfg/dg)*m_cont*f*fg^(m_cont - 2) + 00134 * (f + g + m_sign*fg)*m_cont*(f*(m_cont - 2)*fg^(m_cont - 3)*dfg/dg + 00135 * fg^(m_cont - 2)) 00136 * = m_cont*g*fg^(m_cont-2) + 00137 * m_sign*(m_cont-1)*f*g*fg^(m_cont-3) + 00138 * m_sign*fg^(m_cont-1) + 00139 * m_cont*f*fg^(m_cont - 2) + m_cont*m_sign*f*g*fg^(m_cont - 3) + 00140 * m_cont*(f + g + m_sign*fg)*((m_cont - 2)*f*g*fg^(m_cont - 4) + 00141 * fg^(m_cont - 2)) 00142 * 00143 * @param f The value of f. 00144 * @param g The value of g. 00145 * @return hfg. 00146 * 00147 * \note Needs to be tested. 00148 */ 00149 virtual double hfg(double f, double g); 00150 virtual Intervald hfg(Intervald f, Intervald g); 00151 00152 /** 00153 * Return the 2nd partial derivative with respect to g 00154 * and g on the two function values. 00155 * 00156 * fg = sqrt(f^2 + g^2) 00157 * dfg/dg = g/fg 00158 * hg = fg^m_cont*(1 + m_sign*g/fg) + 00159 * (f + g + m_sign*fg)*m_cont*g*fg^(m_cont - 2) 00160 * = fg^m_cont + m_sign*g*fg^(m_cont-1) + 00161 * (f + g + m_sign*fg)*m_cont*g*fg^(m_cont - 2) 00162 * hgg = m_cont*fg^(m_cont-1)*dfg/dg + 00163 * m_sign*g*(m_cont-1)*fg^(m_cont-2)*dfg/dg + 00164 * m_sign*fg^(m_cont-1) + 00165 * (1 + m_sign*dfg/dg)*m_cont*g*fg^(m_cont - 2) + 00166 * (f + g + m_sign*fg)*m_cont*(g*(m_cont - 2)*fg^(m_cont - 3)*dfg/dg + 00167 * fg^(m_cont - 2)) 00168 * = m_cont*g*fg^(m_cont-2) + 00169 * m_sign*(m_cont-1)*g^2*fg^(m_cont-3) + 00170 * m_sign*fg^(m_cont-1) + 00171 * m_cont*g*fg^(m_cont - 2) + m_cont*m_sign*g^2*fg^(m_cont - 3) + 00172 * m_cont*(f + g + m_sign*fg)*((m_cont - 2)*g^2*fg^(m_cont - 4) + 00173 * fg^(m_cont - 2)) 00174 * 00175 * @param f The value of f. 00176 * @param g The value of g. 00177 * @return hgg. 00178 * 00179 * \note Needs to be tested. 00180 */ 00181 virtual double hgg(double f, double g); 00182 virtual Intervald hgg(Intervald f, Intervald g); 00183 }; 00184 00185 #endif 00186
1.3.4