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 * Jeff Lait 00008 * Side Effects Software Inc 00009 * 477 Richmond Street West 00010 * Toronto, Ontario 00011 * Canada M5V 3E7 00012 * 416-504-9876 00013 * 00014 * NAME: GEO_PointTree.h ( GEO Library, C++) 00015 * 00016 * COMMENTS: This provides a method to index points inside of a 00017 * geometry. 00018 */ 00019 00020 #ifndef __GEO_PointTree__ 00021 #define __GEO_PointTree__ 00022 00023 #include "GEO_API.h" 00024 #include <UT/UT_KDTree.h> 00025 #include <UT/UT_PointTree.h> 00026 #include <UT/UT_IntArray.h> 00027 #include <UT/UT_Vector3Array.h> 00028 #include <UT/UT_PtrArray.h> 00029 00030 class GB_PointGroup; 00031 class GEO_Detail; 00032 class GEO_Point; 00033 00034 class GEO_API GEO_PointTree : protected UT_KDTree 00035 { 00036 public: 00037 GEO_PointTree(); 00038 virtual ~GEO_PointTree(); 00039 00040 /// Rebuilds the PointTree with the given detail and values. 00041 /// It will make its own internal vector3 array of the points and 00042 /// original indices. 00043 void build(const GEO_Detail *gdp, 00044 const GB_PointGroup *ptgroup); 00045 00046 /// Rebuilds the PointTree given a list of GEO_Points. 00047 /// It will make its own internal vector3 array of the points and 00048 /// original indices. 00049 void build(const GEO_Detail *gdp, 00050 const UT_PtrArray<GEO_Point *> &ptlist); 00051 00052 /// Rebuilds the point tree as a pure index based tree using the 00053 /// given vectors. 00054 void build(const UT_Vector3Array &pts); 00055 00056 /// Rebuilds the point tree as a pure index based tree using the 00057 /// given vector/index lookup. 00058 void build(const UT_Vector3Array &pts, 00059 const UT_IntArray &idx); 00060 00061 /// This will slowly build the tree in place. 00062 /// Balancing isn't done until the next lookup. 00063 /// Thus, it can provide a nicer way to initialize a tree. 00064 /// When auto_rebalance is true, the tree may choose not to rebalance on 00065 /// the next lookup, and will rebalance after a sufficient number of 00066 /// points have been added. This can be useful in cases where lookups and 00067 /// appends are interleaved. When it is false, the tree will be rebalanced 00068 /// on the next query. 00069 void append(const GEO_Detail *gdp, const GEO_Point *pt, 00070 bool auto_rebalance=false); 00071 void append(const UT_Vector3 &pt, int idx, 00072 bool auto_rebalance=false); 00073 void append(const UT_Vector3 &pt, 00074 bool auto_rebalance=false); 00075 00076 /// This builds a tree which has a per point radius. 00077 /// Note that this does not work with the tube testing code. 00078 /// Note that there is a large performance penalty for the 00079 /// findNearest methods, but no real penalty for the findAllClose 00080 /// methods 00081 /// If any points are added in radius mode, ALL must be added in 00082 /// radius mode. 00083 void appendPtRadius(const GEO_Detail *gdp, 00084 const GEO_Point *pt, 00085 fpreal radius); 00086 void appendPtRadius(const UT_Vector3 &pt, fpreal radius, 00087 int idx); 00088 void appendPtRadius(const UT_Vector3 &pt, fpreal radius); 00089 00090 /// This makes the tree hard. This makes any attempt to do a GEO_Point 00091 /// look up illegal - one must instead fetch by index. 00092 void harden(); 00093 00094 /// This makes the tree soft. The given GEO_Detail becomes the relevant 00095 /// GEO_Detail for all look ups involving GEO_Points. 00096 void soften(const GEO_Detail *gdp); 00097 00098 /// Clears out the tree, leaving it with no entries and no bound gdp. 00099 void clear(); 00100 00101 /// Returns the number of actual points in the tree. 00102 int entries() const; 00103 00104 /// Returns the amount of memory used by this tree. 00105 int64 getMemoryUsage() const; 00106 00107 /// This sets the valid function method. This call back will be 00108 /// called for each point to see if it should be included in the search. 00109 /// This only works for non-hard trees! 00110 void setValidCallback(UT_PointTreeValidNearestFunc, 00111 void *user_data); 00112 00113 /// Finds the nearest point or index to the given value. Returns 00114 /// 0 or -1 on no such point. 00115 /// NOTE: findNearestPt() will fail if it has not been built with a gdp 00116 GEO_Point *findNearestPt(const UT_Vector3 &pt); 00117 int findNearestIdx(const UT_Vector3 &pt); 00118 00119 /// Finds the nearest point or index to the given value. Returns 00120 /// 0 or -1 on no such point. The point must be within the given range. 00121 /// NOTE: findNearestPt() will fail if it has not been built with a gdp 00122 GEO_Point *findNearestPt(const UT_Vector3 &pt, fpreal maxdist); 00123 int findNearestIdx(const UT_Vector3 &pt, fpreal maxdist); 00124 00125 /// These use a pre-built queue to reduce memory allocation 00126 /// You must call UT_KDTree::destroyQueue() when you are done with 00127 /// the queue. 00128 ut_KDPQueue *createFindNearestQueue(fpreal maxdist = 1e18f) const; 00129 GEO_Point *findNearestPtQueue(const UT_Vector3 &pt, ut_KDPQueue &q); 00130 int findNearestIdxQueue(const UT_Vector3 &pt, ut_KDPQueue &q); 00131 00132 /// Find the nearest [groupsize] points not more than maxdist 00133 /// away. 00134 /// Returns the number of points found. Found points will be 00135 /// stored in the group array. 00136 /// The resulting points will be sorted by their distance. 00137 /// NOTE: findNearestGroupPt() will fail if it has not been built with a gdp 00138 int findNearestGroupPt(const UT_Vector3 &pt, 00139 fpreal maxdist, 00140 int groupsize, 00141 UT_PtrArray<GEO_Point *> &group, 00142 UT_FloatArray &groupdist); 00143 int findNearestGroupIdx(const UT_Vector3 &pt, 00144 fpreal maxdist, 00145 int groupsize, 00146 UT_IntArray &group, 00147 UT_FloatArray &groupdist); 00148 00149 /// Finds all the points within the given radius of a point. 00150 /// The resulting points will *not* be sorted. 00151 /// NOTE: findAllClosePt() will fail if it has not been built with a gdp 00152 int findAllClosePt(const UT_Vector3 &pt, float maxdist, 00153 UT_PtrArray<GEO_Point *> &list); 00154 int findAllCloseIdx(const UT_Vector3 &pt, float maxdist, 00155 UT_IntArray &list); 00156 00157 /// Creates a search queue useful for findAll queries. You 00158 /// must destroy it with UT_KDTree::destroyQueue(q) when done. 00159 ut_KDPQueue *createFindAllQueue(fpreal maxdist) const; 00160 int findAllCloseIdxQueue(const UT_Vector3 &pt, ut_KDPQueue &queue, UT_IntArray &list); 00161 00162 00163 /// Find all of the points inside the given tube. 00164 /// NOTE: findAllInTubePt() will fail if it has not been built with a gdp 00165 int findAllInTubePt(const UT_Vector3 &orig, 00166 const UT_Vector3 &dir, 00167 fpreal radius, 00168 UT_PtrArray<GEO_Point *> &list); 00169 int findAllInTubeIdx(const UT_Vector3 &orig, 00170 const UT_Vector3 &dir, 00171 fpreal radius, 00172 UT_IntArray &list); 00173 00174 /// Takes an index and returns the corresponding point. Only valid if it 00175 /// was built with a gdp and harden() has not been called. Otherwise, it 00176 /// will always return NULL. 00177 GEO_Point *convertIdxToPoint(int idx) const; 00178 00179 /// Sets the myPointTransform member so that we can build our tree from 00180 /// a piece of geometry with an implicit transform on it. 00181 void setPointTransform(const UT_DMatrix4 &xform); 00182 00183 /// Ensures the KD tree has been fully built. If a KD tree 00184 /// is being shared among multiple threads, it is important it 00185 /// has first been compiled on one thread to avoid race conditions 00186 /// (GEO_PointTree is thread safe on read provided it has been built 00187 /// and provided no new points are added to it) 00188 void ensureTreeBuilt() { updateKDTree(); } 00189 00190 protected: 00191 /// These are used by KDTree: 00192 virtual int comparePosition(int idx0, int idx1, int dim) const; 00193 virtual const fpreal*getP(int idx) const; 00194 virtual bool isValid(int idx) const; 00195 00196 /// These are used if the user adds points with radii. 00197 virtual bool pointsHaveRadius() const; 00198 virtual fpreal getRadius(int idx) const; 00199 00200 00201 /// Should be called prior to any invocation of KD Tree methods 00202 /// as it ensures the KDTree knows about the current number of 00203 /// entries. 00204 void updateKDTree(); 00205 00206 /// Marks the kd tree as out of date. 00207 void dirtyKDTree() { myIsKDTreeDirty = true; } 00208 00209 protected: 00210 /// Clears the myPointTransform member data. 00211 void clearPointTransform(); 00212 00213 /// This is the gdp we were built from. 0 if we are hardened. 00214 GEO_Detail *myGdp; 00215 00216 /// If this pointer is set, then before adding any GEO_Points to 00217 /// our point list, we transform their position with this matrix. 00218 UT_DMatrix4 *myPointTransform; 00219 00220 /// This is the mapping from the KD entries into the GDP numbers. 00221 UT_IntArray myIndexList; 00222 00223 /// The list of all the points. 00224 UT_Vector3Array myPointList; 00225 00226 /// List of radii for each pont. 00227 UT_FloatArray myRadii; 00228 00229 /// Tracks if the underlying KDtree has knowledge of our current 00230 /// size. 00231 bool myIsKDTreeDirty; 00232 00233 /// This tracks the callback for the valid nearest function. 00234 UT_PointTreeValidNearestFunc myValidNearestFunc; 00235 void *myValidNearestData; 00236 }; 00237 00238 #endif
1.5.9