00001 /* 00002 * PROPRIETARY INFORMATION. This software is proprietary to 00003 * Side Effects Software Inc., and is not to be reproduced, 00004 * transmitted, or disclosed in any way without written permission. 00005 * 00006 * Produced by: 00007 * Cristin Barghiel 00008 * Side Effects Software Inc. 00009 * 20 Maud St. 00010 * Toronto, Ontario, M5V 2M5 00011 * Canada 00012 * 416-366-4607 00013 * 00014 * NAME: Geometry Library (C++) 00015 * 00016 * COMMENTS: 00017 * This class handles curves of arbitrary degree. 00018 * The Face class maintains the control vertices for the curve. 00019 * 00020 */ 00021 00022 #ifndef __GD_Curve_h__ 00023 #define __GD_Curve_h__ 00024 00025 #include "GD_API.h" 00026 #include <GB/GB_Basis.h> 00027 #include "GD_Face.h" 00028 #include "GD_PrimType.h" 00029 00030 class UT_Vector3; 00031 class UT_Vector2; 00032 00033 class GD_API GD_Curve : public GD_Face 00034 { 00035 public: 00036 // Constructor that attaches this curve to detail "d". 00037 GD_Curve(GD_Detail *d); 00038 00039 // Class destructor, virtual by inheritance. It assumes it is OK to 00040 // delete the basis, so make sure you always set the basis with an object 00041 // allocated from the heap. 00042 virtual ~GD_Curve(); 00043 00044 // Overwrite this curve with the data from src. Virtual by inheritance. 00045 virtual GD_Primitive *copy(int preserve_shared_pts = 0) const; 00046 virtual int copy(const GD_Primitive &src, int ptoffset); 00047 00048 00049 // Return the bounds of the valid evaluation interval in domain space: 00050 virtual void validInterval(int &a, int &b ) const; 00051 virtual void validRange (float &ua, float &ub) const; 00052 00053 // Evaluate one point (when du=0), or the du-th derivative. 00054 // Return 0 if successful, and -1 otherwise. 00055 virtual int evaluate(float u, UT_Vector3 &pos, 00056 unsigned du=0, int uOffset=-1) const; 00057 00058 // Given a domain value (u), store all the basis derivatives (from 0 to du 00059 // inclusive) into bmatx. Return the min and max index of the CVs needed 00060 // for the linear combination. The indices may exceed the number of 00061 // vertices if the curve is wrapped, so remember to use % getVertexCount(). 00062 virtual int evaluateBasisDerivs(float u,float bmatx[][GB_MAXORDER], 00063 int &cvoffset, unsigned du = 0, 00064 int uoffset = -1) const = 0; 00065 00066 // Evaluate the basis at the given point in the domain and also return 00067 // the index of the first CV to linearly combine the basis with. The CV 00068 // index may exceed the number of vertices if the curve is wrapped, 00069 // so remember to use modulus (%). This method handles both rational and 00070 // non-rational curves. 00071 virtual int evaluateBasis(float u,float *ubvals, int &cvoffset, 00072 unsigned du=0, int uoffset=-1) const = 0; 00073 00074 // Return the value of the i'th basis at parameter u. This method handles 00075 // both rational an non-rational curves. 00076 float computeBValue(float u, int i) const; 00077 00078 // Evaluate the curvature at (u). Return 0 if successful and -1 otherwise. 00079 int curvature(float u, UT_Vector2 &curv) const; 00080 00081 // Evaluate the curve betw. breakpoints by taking a start and a stop index 00082 // in the valid knot domain and an lod representing number of points to 00083 // be interpolated between every two breakpoints. The methods ALWAYS 00084 // interpolate the encountered breakpoints (aka "edit points").They return 00085 // the number of points in the list or -1 if unsuccessful. Please save 00086 // yourself headaches and pass VALID start and end indices (see the 00087 // method validInterval() in GB_Basis). 00088 virtual int evaluateBreakSegm(int uStartIdx, int uStopIdx, 00089 int lod, UT_Vector3 *pos, unsigned du=0) const; 00090 00091 // Given a CV index figure out the min/max indicies of the knots between 00092 // which the curve needs to be re-evaluated if the CV changes. If not 00093 // given a valid CV index, the method returns -1. Otherwise it returns 0. 00094 virtual int domainRangeOfCV(int cvidx, int &mink, 00095 int &maxk) const = 0; 00096 00097 // Take the weights into consideration or don't. If you do, the curve 00098 // becomes a rational, and possibly different algorithms apply. If 'onOff' 00099 // is true, this function first checks if any two weights are different 00100 // before setting the rational flag to TRUE; if they are all the same, 00101 // the curve is set to non-rational (=> faster evaluation). weights() 00102 // calls normalizeWeights() to bring the weights to standard form, and 00103 // invokes recordChanges() if necessary. Weights that are <= 0 are bumped 00104 // up to FLT_EPSILON. 00105 virtual void weights(unsigned short onOff); 00106 00107 // Find out whether the curve is currently computed as a rational: 00108 int isRational(void) const { return (int) theRational; } 00109 00110 // Homogenize the curve and disable the "rational" flag. Use the method 00111 // cvRangeOfDomain() to figure out the cv range given a domain range. 00112 void makeHomogeneous(int startcv = 0, int endcv = -1) 00113 { 00114 homogenize(startcv, endcv); 00115 theRational = 0; 00116 } 00117 void makeNonHomogeneous(int startcv = 0, int endcv = -1) 00118 { 00119 dehomogenize(startcv, endcv); 00120 theRational = 1; 00121 } 00122 00123 // Normalize the weights of the control mesh so that edge weights are 1, 00124 // and all weights are >= 0 (those that are <= 0 are bumped up to 00125 // FLT_EPSILON). 00126 void normalizeWeights(); 00127 00128 // Normalize the domain and optionally shift it to a new origin. Use the 00129 // given length if greater than 0. 00130 void normalizeDomain(float len = 0.0F, float *neworigin = 0) 00131 { 00132 uBasis->normalize(len, neworigin); 00133 } 00134 00135 // Set or query the basis. The "set" function overwrites the current 00136 // basis pointer, so use with care; it returns -1 if the basis is invalid. 00137 int setBasis(GB_Basis *ub) 00138 { 00139 if (ub && ub->validate((int)getVertexCount(),(int)isClosed())) 00140 { 00141 delete uBasis; uBasis = ub; 00142 return 0; 00143 } 00144 else return -1; 00145 } 00146 GB_Basis* getBasis(void) const { return uBasis; } 00147 void setAnyBasis(GB_Basis *ub) // Use with care! 00148 { 00149 delete uBasis; uBasis = ub; 00150 } 00151 00152 // Query the order and the dimension of the basis. 00153 virtual unsigned getOrder(void) const; 00154 unsigned getDim(void) const { return (unsigned)uBasis->getDimension(); } 00155 00156 // Inherited from the base class: just checks the validity of the basis. 00157 virtual int isDegenerate(void) const; 00158 00159 // Reverses the vertices of a given face. It's virtual because some faces, 00160 // such as rational splines, need to be aware of it. 00161 virtual void reverse(); 00162 00163 // Dehomogenize data: 00164 static void dehomogenizeData(UT_Vector3 *pos, int count); 00165 00166 protected: 00167 // The basis. Not const because we want to be able to (re)set it at 00168 // initialization time or elsewhere. It must be assigned an object 00169 // allocated from the heap so that we can delete it when calling this 00170 // class's destructor. 00171 GB_Basis *uBasis; 00172 00173 // Load and save functions redefined from the parent class. 00174 virtual int savePrivate(ostream &os, int binary) const; 00175 virtual bool loadPrivate(UT_IStream &is); 00176 00177 // Get a new basis of a type that matches our type: 00178 virtual GB_Basis *newBasis(void) const = 0; 00179 00180 // Check the validity of the data. Meant to be called especially at loading 00181 // time, since it also checks the weights. The method returns 1 if OK and 00182 // 0 if trouble. 00183 virtual bool validate(void) const; 00184 00185 // Set the order of the basis: 00186 void setOrder(unsigned ord) { uBasis->setOrder(ord); } 00187 00188 // Turn the rational flag on or off. Use with discretion. 00189 void rational(int yesno) { theRational = (unsigned short)yesno; } 00190 00191 // Build the vextex list, and optionally append points to the detail. 00192 // Return 0 if OK, and -1 if error. 00193 int create(GD_Curve *crv, int nelems, int closed, 00194 int appendPoints = 1); 00195 virtual int breakCount() const; 00196 00197 00198 private: 00199 // Flag that indicates whether the CV weights should be taken into account 00200 // when evaluating the curve or otherwise affecting its geometry. 00201 unsigned short theRational; 00202 00203 // Evaluate one point of a RATIONAL curve (when du=0), or the du-th 00204 // derivative. Return 0 if successful, and -1 otherwise. 00205 int evaluateRational(float u, UT_Vector3 &pos, 00206 unsigned du=0, int uOffset=-1) const; 00207 00208 // Given a derivative count (du), compute the numerator (aders) and 00209 // denominator (wders) of the expression that gives the curve value 00210 // for all derivatives from 0 to du. Return 0 if OK and -1 otherwise. 00211 int linearCombine(float bmatx[][GB_MAXORDER], 00212 unsigned du, int cvoffset, UT_Vector3 *aders, 00213 float *wders) const; 00214 00215 friend ostream &operator<<(ostream &os, const GD_Curve &d) 00216 { 00217 d.save(os, 0); 00218 return os; 00219 } 00220 }; 00221 00222 #endif
1.5.9