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 * 477 Richmond Street West 00010 * Toronto, Ontario 00011 * Canada M5V 3E7 00012 * 416-504-9876 00013 * 00014 * NAME: Domain pasting Library (C++) 00015 * 00016 * COMMENTS: Paste DAG class. 00017 * 00018 */ 00019 00020 #ifndef __GP_DomainDAG_h__ 00021 #define __GP_DomainDAG_h__ 00022 00023 #include "GP_API.h" 00024 #include <limits.h> 00025 #include "GP_Graph.h" 00026 #include "GP_Domain.h" 00027 00028 class GP_NodeList; 00029 class GP_NodeTree; 00030 00031 class GP_API GP_DomainDAG : public GP_Graph 00032 { 00033 public: 00034 // C-tor with 0 nodes. Can't paste on it. 00035 GP_DomainDAG(void); 00036 00037 // The root this c-tor assigns to myRoot cannot be already pasted somewhere 00038 // else. 00039 GP_DomainDAG(GP_Domain *root); 00040 00041 // Shallow copy c-tor: same nodes, but different lists. 00042 GP_DomainDAG(const GP_DomainDAG&); 00043 00044 // D-tor that destroys all the nodes (thanks to its base class). 00045 virtual ~GP_DomainDAG(void); 00046 00047 // Clear the graph, ie. shrink the domain list to 0 without deleting 00048 // the domains themselves, or destroy the domains as well: 00049 virtual void clear(void); 00050 virtual void clearAndDestroy(int total = 1); 00051 00052 // Copy the source data into us. This is not a complete copy because 00053 // it doesn't resolve the issue of domain surface ownership. 00054 void copyFrom(const GP_DomainDAG &srcdag); 00055 00056 // Copy from the source. Shallow in the nodes. All out nodes are 00057 // destroyed first. Be careful. 00058 GP_DomainDAG &operator=(const GP_DomainDAG &src); 00059 00060 // Check if the domain or the dag would fit into our root domain. "parents" 00061 // emerges with a list of would-be top container parents. 00062 int canPaste(GP_Domain &d); 00063 int canPaste(GP_Domain &d, GP_NodeList &parents); 00064 int canPaste(GP_DomainDAG &dag) 00065 { 00066 return dag.myRoot ? canPaste(*dag.myRoot) : 0; 00067 } 00068 int canPaste(GP_DomainDAG &dag,GP_NodeList &parents) 00069 { 00070 return dag.myRoot?canPaste(*dag.myRoot,parents):0; 00071 } 00072 int canPaste(GP_DomainDAG &dag, GP_Domain &parent, 00073 const UT_BoundingRect &brect); 00074 00075 // Find out if we're in a paste graph, ie. if we have a parent or not: 00076 int isPasted() const 00077 { 00078 return (myRoot && myRoot->isFeature()); 00079 } 00080 00081 // Paste the dag onto us if it fits, and return its root. "parents" holds 00082 // the list of would-be to container domains. 00083 GP_Domain *paste(GP_DomainDAG &child, int keepshape = 0); 00084 GP_Domain *paste(GP_DomainDAG &child, GP_NodeList &parents, 00085 int keepshape = 0); 00086 00087 // Paste the srcdag onto us after checking if the 4 domain world points 00088 // are in our transformed root domain. Return the root of the srdag or 0. 00089 GP_Domain *paste(GP_DomainDAG &srcdag, 00090 const GP_Point &b1, const GP_Point &b2, 00091 const GP_Point &b3, const GP_Point &b4); 00092 00093 // Unpaste a domain alone or with all its contained children. If you know 00094 // what the contained set is, pass it in for speed. If you unpaste the 00095 // root domain, the whole dag goes. 00096 GP_Domain *unpasteAt (GP_Domain &child); 00097 GP_DomainDAG *unpasteFrom(GP_Domain &child, GP_NodeTree *ctree=0); 00098 00099 // Delete a domain alone or with all its contained children. If you know 00100 // what the contained set is, pass it in for speed. If you delete the root 00101 // domain all the kids will be unpasted. Return 0 upon success, or -1. 00102 int destroyAt (GP_Domain &child); 00103 int destroyFrom(GP_Domain &child, GP_NodeTree *ctree=0); 00104 00105 // Replace a domain alone or with all its contained children with a new 00106 // DAG. If you know the domain's contained set, pass it in for speed. 00107 // The method returns dag's root or 0. 00108 GP_Domain *replaceAt (GP_Domain &child, GP_DomainDAG &dag); 00109 GP_Domain *replaceFrom(GP_Domain &child, GP_DomainDAG &dag, 00110 GP_NodeTree *ctree = 0); 00111 00112 // Similar to paste, only if the child or its contained DAG has bridges, 00113 // the bridges will be raised before pasting, then lowered again. If 00114 // you know child's contained nodes, pass them in for speed. We return 00115 // dag's root or 0. 00116 GP_Domain *overlayAt (GP_Domain &child, GP_DomainDAG &dag, 00117 int keepshape = 0); 00118 GP_Domain *overlayAt (GP_Domain &child, GP_DomainDAG &srcdag, 00119 const UT_BoundingRect &brect); 00120 GP_Domain *overlayAt (GP_Domain &child, GP_DomainDAG &srcdag, 00121 const GP_Point &b1, const GP_Point &b2, 00122 const GP_Point &b3, const GP_Point &b4); 00123 GP_Domain *overlayFrom(GP_Domain &child, GP_DomainDAG &dag, 00124 GP_NodeTree *ctree=0, int keepshape = 0); 00125 GP_Domain *overlayFrom(GP_Domain &child, GP_DomainDAG &dag, 00126 const GP_Point &b1, const GP_Point &b2, 00127 const GP_Point &b3, const GP_Point &b4, 00128 GP_NodeTree *ctree=0); 00129 00130 // Remove the child. This is an alias for unpasteAt() and doesn't need 00131 // to be redefined in the derived classes. 00132 GP_Domain *removeAt(GP_Domain &child) 00133 { 00134 return GP_DomainDAG::unpasteAt(child); 00135 } 00136 00137 // Anything goes in terms of spline surface changes, especially if it 00138 // involves changes of both knots and CVs, as in refinement, unrefinement, 00139 // degree elevation, or cutting. If "standalone" is 1, we bring the 00140 // child back to its unpasted shape before calling (*apply)(). 00141 // Return 0 if OK, else -1. 00142 int modifyBasis(GP_Domain &child, 00143 int (*apply)(void *tpsurf, void *d), 00144 void *data = 0, 00145 int standalone = 0); 00146 00147 // Add a layer by spawning a domain definitely contained within the child. 00148 // Return that domain if everything is successful, else 0. The child 00149 // in the domain area defined by brect, and the ub/vb stuff are belt 00150 // reinforcements. 00151 GP_Domain *spawn(GP_Domain &child, const UT_BoundingRect &brect, 00152 float ubwidth = 0, float vbwidth = 0, 00153 int ubdivs = 2, int vbdivs = 2); 00154 00155 // See if we contain this world domain point. A quick check does only a 00156 // bbox test: 00157 int contains(const GP_Point &worldp, int quick = 0) const 00158 { 00159 return myRoot ? myRoot->contains(worldp,quick):0; 00160 } 00161 00162 // See if d is pasted on us by checking its anchor against our root: 00163 int contains(const GP_Domain &d) const 00164 { 00165 return myRoot 00166 ? myRoot->frames()==d.frames()->anchor() : 0; 00167 } 00168 00169 // Method to change the key of a domain while preserving the sanity of the 00170 // graph. Return the changed node or 0 if not found. The fast method does 00171 // not remove and reinsert the domain. 00172 GP_Domain *keyUp(GP_Domain &domain) 00173 { 00174 return (GP_Domain*)rekey(domain, myLabel++); 00175 } 00176 void keyUpFast(GP_Domain &domain) 00177 { 00178 domain.key(myLabel++); 00179 } 00180 00181 // Return top-most domain that worldp lies inside, or 0. 00182 GP_Domain *topDomain(const GP_Point &worldp) const; 00183 00184 // Change the root transformation given a handle or a domain. This will set 00185 // everything dirty. The domain isn't const because it might need to be 00186 // updated. 00187 void changeRootXform(const GP_XformHandle &handle); 00188 void changeRootXform(GP_Domain &d); 00189 00190 // Assuming "child" is the root of a newly pasted DAG, link it to its 00191 // parent domain(s) (top containers) in our DAG. The methods make sure 00192 // everything is (re)pasted and updated accordingly. The bases are 00193 // already set at this point by findParents(). 00194 virtual void link(GP_Domain &child, GP_NodeList &parents, 00195 int keepshape = 0); 00196 virtual void link(GP_Domain &child, GP_Domain &parent, 00197 int withcorrection = 1); 00198 00199 // Assuming child is pasted on us, update the pasted image of all of 00200 // surf's descendents in pasted order. surf is not updated. 00201 // Return 0 upon success, else -1. 00202 virtual int updateDescendents(GP_Domain &child, 00203 int including_child = 0); 00204 00205 // Some vertices (or all) have changed, so reverse engineer the 00206 // displacements from the CVs of the spline surface. In other words, 00207 // given the local frames and the GEO_Points, build the displacements for 00208 // the child node, then update its descendents. Return -1 if not our child. 00209 virtual int updateDisplacements(GP_Domain &child, 00210 int keepframes = 1); 00211 00212 // The public can only look at the root but not change it because things 00213 // are tricky in the hierarchy: 00214 const GP_Domain *root(void) const { return myRoot; } 00215 00216 00217 protected: 00218 // Let us know when something has changed in the root domain. 00219 virtual void changedRoot(void); 00220 00221 // Tell the dag it's obsolete. This will happen when the dag has been 00222 // pasted onto some other dag, and should be deleted. This method clears 00223 // the nodes. Derived classes will probably "delete this" inside it, 00224 // so don't use the dag thereafter. 00225 virtual void obsolete(void); 00226 00227 // Build a sorted list of nodes representing the contained DAG rooted at 00228 // base, base included. You must free it yourself. 00229 GP_NodeTree *containedDomains(const GP_Domain& base) const; 00230 00231 // root must be stand-alone. Don't do it if we have a root already. Use 00232 // modifyAt() instead. The method returns root or 0 if failure. 00233 GP_Domain *insertRoot(GP_Domain &root); 00234 00235 // Just adds this one to the node, and bumps up our label count. 00236 void insertDomain(GP_Domain &domain); 00237 00238 // Relabel the whole DAG from a given value and update myLabel. 00239 void relabel(int start = INT_MIN); 00240 00241 // Use this method after loading to make sure all the proper links are 00242 // set. ONLY after loading. Return 0 is OK and -1 otherwise. 00243 int pasteInPlace(GP_Domain &child); 00244 00245 // Derived classes get a full look at the root with a non-const handle: 00246 GP_Domain *root(void) { return myRoot; } 00247 00248 00249 private: 00250 GP_Domain *myRoot; // root domain 00251 int myLabel; // current label for nodes 00252 00253 00254 // Private c-tor that assigns "root" to its root and grabs the nodes 00255 // from the node tree. The structures will not be the same, but the 00256 // nodes will be shared: 00257 GP_DomainDAG(GP_Domain *root, GP_NodeTree &cnodes); 00258 00259 // Given a domain or its immediate parents, find the root of the shortest 00260 // contained DAG that would contain the domain or its given parents. 00261 GP_Domain *minContainment(GP_Domain &domain); 00262 GP_Domain *minContainment(GP_NodeList &parents); 00263 00264 public: // raiseBridges() is called from within a static callback... 00265 // Assuming base is in our graph, raise the bridges recursively. 00266 void raiseBridges(GP_Domain &d); 00267 00268 // Return a list of domains d would touch if pasted here. We assume d 00269 // would fit in the root domain. Unlike canPaste(), this method ignores 00270 // nodes currently not linked up. "parents" contains domains in decreasing 00271 // key order. 00272 GP_NodeList &underDomains(GP_Domain &d, GP_NodeList &parents); 00273 private: 00274 00275 // This method assumes the child is pasted onto this dag, and removes 00276 // its frame links, the node from the graph, and sets its dag pointer 00277 // to nil. If this is the root, it sets myRoot to zero. 00278 void isolate(GP_Domain &child); 00279 00280 // Detach the high bridges (ie. here the immediate children) of the node. 00281 // The method returns an ordered list of detached nodes. These nodes will 00282 // only have links to the contained DAG they are the roots of. You must 00283 // free this list yourself. 00284 GP_NodeTree *raiseBridgesAt(GP_Domain &node); 00285 00286 // Raise bridges from a base node or from a list of contained nodes. 00287 // The resulting nodes will only have links to the contained DAG they are 00288 // the roots of. You must free this list yourself. 00289 GP_NodeTree *raiseBridgesFrom(GP_Domain &base); 00290 GP_NodeTree *raiseBridgesFrom(GP_NodeTree &nodes); 00291 00292 // Relink the bridges by pasting them again in the order in which they 00293 // had been pasted originally. 00294 void lowerBridges(GP_NodeTree &bridges, int relabel = 0); 00295 }; 00296 00297 #endif
1.5.9