vclip.h
Go to the documentation of this file.
1 //
3 // Copyright 1997 Mitsubishi Electric Information Technology Center
4 // America (MEITCA). All Rights Reserved.
5 //
6 // Permission to use, copy, modify and distribute this software and
7 // its documentation for educational, research and non-profit
8 // purposes, without fee, and without a written agreement is hereby
9 // granted, provided that the above copyright notice and the
10 // following three paragraphs appear in all copies.
11 //
12 // Permission to incorporate this software into commercial products
13 // may be obtained from MERL - A Mitsubishi Electric Research Lab, 201
14 // Broadway, Cambridge, MA 02139.
15 //
16 // IN NO EVENT SHALL MEITCA BE LIABLE TO ANY PARTY FOR DIRECT,
17 // INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
18 // LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
19 // DOCUMENTATION, EVEN IF MEITCA HAS BEEN ADVISED OF THE POSSIBILITY
20 // OF SUCH DAMAGES.
21 //
22 // MEITCA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 // FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON
25 // AN "AS IS" BASIS, AND MEITCA HAS NO OBLIGATIONS TO PROVIDE
26 // MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
27 //
28 // Author:
29 // Brian Mirtich
30 // mirtich@merl.com
31 // 617.621.7573
32 // www.merl.com/people/mirtich
33 //
35 
36 
37 
38 #ifndef VCLIP_H
39 #define VCLIP_H
40 
41 #include <list>
42 #include <map>
43 #include <string.h>
44 
45 #include "mv.h"
46 
47 #if INVENTOR
48 #include <Inventor/nodekits/SoShapeKit.h>
49 #endif
50 
51 using namespace std;
52 namespace Vclip {
54 // constants
56 
57 
58 #define VF_NAME_SZ 15 // max # of chars in a Face or Vertex name (incl. \0)
59 #define PTREE_NAME_SZ 80 // max # of chars in a PolyTree name (including \0)
60 
61 typedef char VertFaceName[VF_NAME_SZ];
62 
63 // Used as the initial size for certain resizable vectors. Generally,
64 // the number defined below is plenty big, however exceeding this
65 // limit at runtime won't break anything.
66 #define MAX_VERTS_PER_FACE 100
67 
68 
70 // data structures
72 
73 template<class T>
74 class Handle {
75  T *ptr;
76 public:
77  void set(T *p) {ptr = p;}
78  Handle() {ptr = NULL;}
79  Handle(T *p) {set(p);}
80  ~Handle() {delete ptr;}
81  T* operator->() {return ptr;}
82  T& operator*() {return *ptr;}
83  const T* operator->() const {return ptr;}
84  const T& operator*() const {return *ptr;}
85 };
86 
87 
88 template<class T>
89 class ShareHandle {
90  T *ptr;
91 public:
92  void set(T *p) {ptr = p; p->handleCount++;}
93  ShareHandle() {ptr = NULL;}
94  ShareHandle(T *p) {set(p);}
95  ShareHandle(const ShareHandle &orig) {set(orig.ptr);}
96  ~ShareHandle() {if (ptr && --ptr->handleCount == 0) delete ptr;}
98  if (ptr && --ptr->handleCount == 0) delete ptr;
99  set(orig.ptr);
100  return *this;
101  };
102  T *operator->() {return ptr;}
103  T &operator*() {return *ptr;}
104  const T* operator->() const {return ptr;}
105  const T& operator*() const {return *ptr;}
106 };
107 
108 
109 
111 // Extensions to SGI's standard library
113 
114 // If using this macro, make sure the list variable is not changed
115 // inside the loop, e.g.:
116 
117 // FOR_EACH(num.primeFactors, itor) {
118 // ...
119 // num = otherNum; // error!
120 // ...
121 // }
122 
123 #ifndef FOR_EACH
124 #define FOR_EACH(list, iterator) \
125  for(iterator = (list).begin(); iterator != (list).end(); ++iterator)
126 #endif
127 
128 
130 // typedef VclipPose
132 
133 // V-Clip can use either class MatX or class Se3 as the basis for pose
134 // specification (see mv.h). Class MatX requires fewer floating point
135 // operations to transform points and vectors. However the Se3
136 // representation may be numerically robust (further study is needed).
137 // During testing, cases were found where V-Clip returned an incorrect
138 // disjoint result for penetrating Polyhedra when using the MatX
139 // representation; this behavior went away when the Se3 representation
140 // was used. These cases were extremely contrived and unlikely to
141 // occur in normal use. The MatX representation is initially
142 // recommended for all applications. If problems occur, consider
143 // switching to the Se3 representation. The interface is the same for
144 // either option, except for the type of the relative pose parameter
145 // Xr1r2 passed to PolyTree::vclip().
146 
147 // define as 1 for MatX pose representation and 0 for Se3 pose
148 // representation.
149 #define VCLIP_MATRIX_POSE 0
150 
151 #if VCLIP_MATRIX_POSE
152 typedef MatX VclipPose;
153 #else
154 typedef Se3 VclipPose;
155 #endif
156 
157 
158 // used in V-Clip to cache transforme geometry
159 struct XformedGeom {
160  const class Feature *feat;
165 };
166 
167 
169 // class Plane
171 
172 
173 class Plane {
174 
175  Vect3 normal_; // plane = { p | < p , normal_ > + offset_ = 0 }
177 
178 public:
179 
180  const Vect3 &normal() const {return normal_;}
181  const Real &offset() const {return offset_;}
182 
183  void set(const Vect3 &normal, const Vect3 &thruPoint)
184  {normal_ = normal; offset_ = - Vect3::dot(thruPoint, normal);}
185 
186  // Compute signed distance from point to plane; assumes unit length normal_
187  Real dist(const Vect3 &point) const
188  {return Vect3::dot(normal_, point) + offset_;}
189 
190  ostream& print(ostream &os) const;
191 };
192 
193 
194 
196 // struct VertConeNode & FaceConeNode
198 
199 
201 {
202  const Plane *plane;
203  class Edge *nbr; // neighboring edge when plane violated
204 
205  ostream& print(ostream &os) const;
206 
207 };
208 
209 
211 {
212  const Plane *plane;
213  const class Edge *nbr; // neighboring edge when plane violated
214 
215  const FaceConeNode *ccw, *cw;
216  int idx; // ranges from 0 to n-1, where n = number of edges on face
217 
218  ostream& print(ostream &os) const;
219 
220 };
221 
222 
223 
225 // class Feature
227 
228 class Feature {
229 
230 public:
231  enum Type {VERTEX, EDGE, FACE};
232 
233 protected:
235 
236 public:
237  Type type() const {return type_;}
238  virtual const char *name() const = 0;
239 };
240 
241 
242 
244 // closest feature pairs and hash table
246 
248 {
249  const class PolyTree *first, *second;
250 };
251 
252 inline int operator==(const PolyTreePair &ptree1, const PolyTreePair &ptree2)
253 {return ptree1.first == ptree2.first && ptree1.second == ptree2.second;}
254 
255 inline int operator<(const PolyTreePair &ptree1, const PolyTreePair &ptree2)
256 {return ptree1 < ptree2;}
257 
258 
260 {
261  const Feature *first, *second;
262  FeaturePair() {first = second = NULL;}
263 };
264 
265 #if 0
266 struct PolyTreePairHasher : unary_function<PolyTreePair, size_t> {
267  size_t operator() (const PolyTreePair &ptrees) const
268  {return ((size_t) ptrees.first)
269  ^ (((unsigned int) ptrees.second) << 16)
270  ^ (((unsigned int) ptrees.second) >> 16);}
271 };
272 #endif
273 
274 typedef
275 std::map<PolyTreePair, FeaturePair>
277 
279 // class Vertex
281 
282 
283 class Vertex : private Feature
284 {
285  friend class Polyhedron;
286  friend class PolyTree;
287 
289  list<VertConeNode> cone;
290  VertFaceName name_;
291 
292 public:
293  Vertex() {type_ = VERTEX;}
294  const char *name() const;
295  const Vect3 &coords() const {return coords_;}
296 
297 };
298 
299 
300 
302 // class Edge
304 
305 
306 class Edge : private Feature
307 {
308  friend class Polyhedron;
309  friend class PolyTree;
310 
311  const Vertex *tail, *head;
312  const class Face *left, *right;
315  Plane tplane, hplane, lplane, rplane;
316 
317  Edge() {type_ = EDGE;}
318 
319 public:
320  const char *name() const;
321 
322 };
323 
324 
325 
327 // class Face
329 
330 
331 class Face : private Feature
332 {
333  friend class Polyhedron;
334  friend class PolyTree;
335 
336  int sides; // number of edges around boundary
338  list<FaceConeNode> cone;
339  VertFaceName name_;
340 
341  Face() {type_ = FACE;}
342 
343 public:
344  const char *name() const;
345 
346 };
347 
348 
349 
351 // class Polyhedron
353 
354 
356 {
357  friend class PolyTree;
358  friend class ShareHandle<Polyhedron>;
359 
360  int handleCount; // number of PolyTrees pointing to thie Polyhedron
361 
362  list<Vertex> verts_;
363  list<Edge > edges_;
364  list<Face > faces_;
365 
366  void processEdge(Face *f, Vertex *tail, Vertex *head);
367 
368  static int vertVertTest(const Feature *&v1, const Feature *&v2,
369  XformedGeom &xv1, XformedGeom &xv2,
370  const VclipPose &X12, const VclipPose &X21,
371  Vect3 &cp1, Vect3 &cp2, Real &dist);
372 
373  static int vertFaceTest(const Feature *&v, const Feature *&f, XformedGeom &xv,
374  const VclipPose &Xvf, const list<Face> &allFaces,
375  Vect3 &cpv, Vect3 &cpf, Real &dist);
376 
377  static int vertEdgeTest(const Feature *&v, const Feature *&e,
378  XformedGeom &xv, XformedGeom &xe,
379  const VclipPose &Xve, const VclipPose &Xev,
380  Vect3 &cpv, Vect3 &cpe, Real &dist);
381 
382  static int edgeEdgeSubtest(const Feature *&e, XformedGeom &xe, Vect3 &cp);
383 
384  static int edgeEdgeTest(const Feature *&e1, const Feature *&e2,
385  XformedGeom &xe1, XformedGeom &xe2,
386  const VclipPose &X12, const VclipPose &X21,
387  Vect3 &cp1, Vect3 &cp2, Real &dist);
388 
389  static int edgeFaceTest(const Feature *&e, const Feature *&f,
390  XformedGeom &xe, const VclipPose &Xef,
391  Vect3 &cpe, Vect3 &cpf, Real &dist);
392 
393  public: static Real vclip(const Polyhedron *const poly1,
394  const Polyhedron *const poly2,
395  const VclipPose &X12, const VclipPose &X21,
396  const Feature *&feat1, const Feature *&feat2,
397  Vect3 &cp1, Vect3 &cp2, int oneStep = 0);
398 
399 #if INVENTOR
400  SoShapeKit *buildInvModel() const;
401 #endif
402 
403 public:
404 
405  Polyhedron() {handleCount = 0;}
406 
407  // construction
408  inline Vertex *addVertex(const char *name, const Vect3 &coords);
409  void addFace(const char *name,
410  vector<Vertex *> &verts, int clockwise = 0);
411  int buildHull();
412  int check() const;
413 
414  // examination
415  ostream& print(ostream &os) const;
416  const list<Vertex> &verts() const {return verts_;}
417  const list<Edge > &edges() const {return edges_;}
418  const list<Face > &faces() const {return faces_;}
419 };
420 
421 
422 
424 // class PolyTree
426 
427 // Since the same Polytree's structure may be used multiple times,
428 // possibly even within the same rigid object, we need a way to refer
429 // to a specific instance of a given PolyTree. The Inventor solution
430 // is to use paths to refer to specific instances of nodes in a scene
431 // graph, so the node doesn't need to be stored twice. Our solution
432 // is simpler: we replicate instances of the PolyTree structures, that
433 // is, every occurrence of the same PolyTree is uniquely stored.
434 // Thus, addresses of PolyTree nodes can unambiguously specify
435 // instances. The Polyhedron structures remain shared: different
436 // PolyTree nodes can point to the same Polyhedron. Since most of the
437 // storage is in the Polyhedron structures, not the PolyTree nodes,
438 // this is not too wasteful. It is also much easier to point to
439 // sepcific instances of PolyTrees than with the path method.
440 
441 // Replication of PolyTree nodes allows us to have different names for
442 // the different instances of the same PolyTree. It also allows the
443 // Tpm field (see below). If PolyTrees were not replicated, there
444 // could be no such field since the same PolyTree node could be shared
445 // by different geometry hierarchies. In this situation, the only
446 // alternative is to store a transformation to the parent's frame, and
447 // accumulate these transformations along a specific path. The
448 // replication approach saves time because the Tpm's can be
449 // precomputed.
450 
451 class PolyTree
452 {
453 
454  friend class PolyTreeLibrary;
455 
456  // Pointer to a Polyhedron. For an atomic PolyTree, this is the
457  // geometry of the PolyTree itself; for a compound PolyTree, this is
458  // the geometry of the convex hull.
460 
461  // Volume integrals, relative to this PolyTree's reference frame
462  Real vol_; // volume: vol = int(dV)
463  Vect3 mov1_; // 1st moment of volume: mov1.x = int(x dV)
464  Vect3 mov2_; // undiagonalized 2nd moment of volume: mov2.x = int(x^2 dV)
465  Vect3 pov_; // product of volume: pov.x = int(yz dV)
466 
467  Real rad_; // "radius" of PolyTree, relative to center of volume
468 
469 
470  // An entire PolyTree shares a common reference frame (r). Tpr_ and
471  // Trp_ are the transformations between each PolyTree's local frame
472  // (p) and the PolyTree reference frame. These fields are
473  // recomputed each time the PolyTree is included (replicated) into
474  // another hierarchy. By default, the reference frame is simply the
475  // local frame of the root PolyTree, so for the root node Tpr_ and
476  // Trp_ are identity transformations. In some cases, however, it is
477  // advantageous to store transformations with respect to a different
478  // frame. For example, in rigid body simulation, an object's body
479  // frame is the most useful frame, so all of the PolyTree nodes in
480  // it's geometry use that as the reference frame. The reference
481  // frame of a hierarchy is updated using the xform() method. Xpr_
482  // and Xrp_ are the MatX_ equivalents of Tpr_ and Trp_.
483  Se3 Tpr_, Trp_;
484  MatX Xpr_, Xrp_;
485 
486  list< Handle<PolyTree> > components; // children in convex decomp'n, if any
487 
488 public:
490 
491 private:
492 
493  void printRecur(ostream &os, int level) const;
494 
495  // copy constructor (perform a deep copy of this)
496  PolyTree(const PolyTree &orig);
497 
498 public:
499 
500  PolyTree();
501 
502  // construction
504  void addComponent(PolyTree *comp)
505  {Handle<PolyTree> h(comp); components.push_back(h); h.set(NULL);}
506  int buildHull();
507  void xform(const Se3 &T);
508 
509  // examination
510  const Polyhedron *poly() const {return &*poly_;}
511  int numNodes() const;
512  int numLeaves() const;
513  ostream& print(ostream &os) const;
514  const Se3 &Tpr() const {return Tpr_;}
515 #if INVENTOR
516  SoNode *buildInvModel() const;
517 #endif
518 
519  // volume integrals
520  void compVolInts();
521  const Real &vol() const {return vol_;}
522  const Vect3 &mov1() const {return mov1_;}
523  const Vect3 &mov2() const {return mov2_;}
524  const Vect3 &pov() const {return pov_;}
525  const Real &rad() const {return rad_;}
526 
527  // V-Clip
528 private:
529  static Real vclip_(
530  const PolyTree *const ptree1, const PolyTree *const ptree2,
531  const VclipPose &Xr1r2, const VclipPose &Xr2r1,
532  ClosestFeaturesHT &ht,
533  Vect3 &cp1, Vect3 &cp2);
534 public:
535 
536  // Application callpoint for V-Clip. Xr1r2 is the transformation
537  // from the reference frame of ptree1 to the reference frame of
538  // ptree2. Cp1 and cp2 are also returned in these frames.
539  inline static Real vclip(const PolyTree *const ptree1,
540  const PolyTree *const ptree2,
541  const VclipPose &Xr1r2,
542  ClosestFeaturesHT &ht,
543  Vect3 &cp1, Vect3 &cp2)
544  {
545  VclipPose Xr2r1;
546  Xr2r1.invert(Xr1r2);
547  return vclip_(ptree1, ptree2, Xr1r2, Xr2r1, ht, cp1, cp2);
548  }
549 
550  // V-Clip does not return closest features to the caller. If they're
551  // needed, this function returns the most recent feature pair for the
552  // given PolyTrees, or NULL is no hash table entry can be found.
553  static void vclipFeatures(
554  const PolyTree *const ptree1,
555  const PolyTree *const ptree2,
556  ClosestFeaturesHT &ht,
557  const Feature *&feat1, const Feature *&feat2);
558 };
559 
560 
561 
563 // class PolyTreeLibrary
565 
566 
568 {
569  list< Handle<PolyTree> > lib;
570 
571 public:
572 
573  void clear() {lib.clear();} // clear out the library
574  int size() {return lib.size();} // return # of entries in lib
575 
576  void add(PolyTree *pt) // add PolyTree to library
577  {Handle<PolyTree> h(pt); lib.push_front(h); h.set(NULL);}
578 
579  const PolyTree *lookup(const char *name) const; // lookup by name
580  const PolyTree *lookup(int i) const; // lookup by index
581 
582  PolyTree *create(const char *name) const // instantiate by name
583  {const PolyTree *pt; return (pt = lookup(name)) ? new PolyTree(*pt) : NULL;}
584 
585  PolyTree *create(int i) const // instantiate by index
586  {const PolyTree *pt; return (pt = lookup(i)) ? new PolyTree(*pt) : NULL;}
587 };
588 
589 
591 // stream operators
593 
594 
595 inline ostream &operator<<(ostream &os, const Plane &p) {return p.print(os);}
596 inline ostream &operator<<(ostream &os, const VertConeNode &vcn)
597  {return vcn.print(os);}
598 inline ostream &operator<<(ostream &os, const FaceConeNode &fcn)
599  {return fcn.print(os);}
600 inline ostream &operator<<(ostream &os, const Polyhedron *poly)
601  {return poly->print(os);}
602 inline ostream &operator<<(ostream &os, const PolyTree *pt)
603  {return pt->print(os);}
604 
605 
606 
608 // inline methods
610 
611 
612 Vertex *Polyhedron::addVertex(const char *name, const Vect3 &coords)
613 {
614  Vertex v;
615  v.coords_ = coords;
616  strcpy(v.name_, name);
617  verts_.push_back(v);
618  return &verts_.back();
619 }
620 
621 
622 
624 // default goemetry readers
626 
627 // Provided for convenience; not part of API.
628 
629 int loadPolyTreeFile(const char *fname, PolyTreeLibrary &library);
630 };
631 #endif // #ifndef VCLIP_H
void setPoly(Polyhedron *p)
Definition: vclip.h:503
Real offset_
Definition: vclip.h:176
T & operator*()
Definition: vclip.h:82
double Real
Definition: mv.h:163
Type type() const
Definition: vclip.h:237
Vect3 coords_
Definition: vclip.h:288
Se3 VclipPose
Definition: vclip.h:154
int operator==(const PolyTreePair &ptree1, const PolyTreePair &ptree2)
Definition: vclip.h:252
ShareHandle(T *p)
Definition: vclip.h:94
#define VF_NAME_SZ
Definition: vclip.h:58
PolyTree * create(int i) const
Definition: vclip.h:585
const list< Vertex > & verts() const
Definition: vclip.h:416
ShareHandle< Polyhedron > poly_
Definition: vclip.h:459
const class Feature * feat
Definition: vclip.h:160
Definition: mv.h:600
list< Vertex > verts_
Definition: vclip.h:362
ostream & print(ostream &os) const
T * ptr
Definition: vclip.h:75
png_infop png_charpp name
list< Handle< PolyTree > > components
Definition: vclip.h:486
const Vect3 & coords() const
Definition: vclip.h:295
const class PolyTree * first
Definition: vclip.h:249
const Polyhedron * poly() const
Definition: vclip.h:510
VertFaceName name_
Definition: vclip.h:339
const list< Face > & faces() const
Definition: vclip.h:418
png_uint_32 i
const FaceConeNode * cw
Definition: vclip.h:215
const Vect3 & mov2() const
Definition: vclip.h:523
ROSCONSOLE_DECL void print(FilterBase *filter, void *logger, Level level, const char *file, int line, const char *function, const char *fmt,...) ROSCONSOLE_PRINTF_ATTRIBUTE(7
Type type_
Definition: vclip.h:234
const Feature * second
Definition: vclip.h:261
list< Edge > edges_
Definition: vclip.h:363
const Vertex * tail
Definition: vclip.h:311
PolyTree * create(const char *name) const
Definition: vclip.h:582
list< Face > faces_
Definition: vclip.h:364
Vect3 normal_
Definition: vclip.h:175
ostream & operator<<(ostream &os, const PolyTree *pt)
Definition: vclip.h:602
const class Face * right
Definition: vclip.h:312
int loadPolyTreeFile(const char *fname, PolyTreeLibrary &library)
void add(PolyTree *pt)
Definition: vclip.h:576
void invert(const Se3 &T)
Definition: mv.h:1499
T * operator->()
Definition: vclip.h:102
const Vect3 & mov1() const
Definition: vclip.h:522
const Vect3 & normal() const
Definition: vclip.h:180
const Plane * plane
Definition: vclip.h:212
Vect3 mov1_
Definition: vclip.h:463
ostream & print(ostream &os) const
ostream & print(ostream &os) const
ostream & print(ostream &os) const
T * operator->()
Definition: vclip.h:81
Plane plane
Definition: vclip.h:337
char VertFaceName[VF_NAME_SZ]
Definition: vclip.h:61
const Se3 & Tpr() const
Definition: vclip.h:514
const T & operator*() const
Definition: vclip.h:105
Vect3 dir
Definition: vclip.h:314
static Real vclip(const PolyTree *const ptree1, const PolyTree *const ptree2, const VclipPose &Xr1r2, ClosestFeaturesHT &ht, Vect3 &cp1, Vect3 &cp2)
Definition: vclip.h:539
T & operator*()
Definition: vclip.h:103
const Plane * plane
Definition: vclip.h:202
const Vect3 & pov() const
Definition: vclip.h:524
ShareHandle(const ShareHandle &orig)
Definition: vclip.h:95
class Edge * nbr
Definition: vclip.h:203
ShareHandle & operator=(const ShareHandle &orig)
Definition: vclip.h:97
Real len
Definition: vclip.h:313
Definition: mv.h:54
list< VertConeNode > cone
Definition: vclip.h:289
const Real & rad() const
Definition: vclip.h:525
Real dist(const Vect3 &point) const
Definition: vclip.h:187
typedef int
const Real & vol() const
Definition: vclip.h:521
#define PTREE_NAME_SZ
Definition: vclip.h:59
VertFaceName name_
Definition: vclip.h:290
Plane tplane
Definition: vclip.h:315
std::map< PolyTreePair, FeaturePair > ClosestFeaturesHT
Definition: vclip.h:276
Vect3 pov_
Definition: vclip.h:465
const T * operator->() const
Definition: vclip.h:83
void addComponent(PolyTree *comp)
Definition: vclip.h:504
Vect3 mov2_
Definition: vclip.h:464
int sides
Definition: vclip.h:336
const Real & offset() const
Definition: vclip.h:181
list< Handle< PolyTree > > lib
Definition: vclip.h:569
ostream & print(ostream &os) const
const list< Edge > & edges() const
Definition: vclip.h:417
const class PolyTree * second
Definition: vclip.h:249
Handle(T *p)
Definition: vclip.h:79
list< FaceConeNode > cone
Definition: vclip.h:338
void set(T *p)
Definition: vclip.h:77
const T * operator->() const
Definition: vclip.h:104
const T & operator*() const
Definition: vclip.h:84
const class Edge * nbr
Definition: vclip.h:213
int operator<(const PolyTreePair &ptree1, const PolyTreePair &ptree2)
Definition: vclip.h:255


hrpsys
Author(s): AIST, Fumio Kanehiro
autogenerated on Thu May 6 2021 02:41:51