//////////////////////////////////////////////////////////////////////// //! file="amma/Surf3d/TriSet/TriSet.hh" //! lib=tri //! userlevel=Normal //! docentry="3D Surface.Polyhedral Representation" //! rcsid="$Id: TriSet.hh,v 1.19 2001/02/07 13:44:59 eep1rs Exp $" //! author="Adrian Hilton" //! date="04/02/96" #include "amma/Tri.hh" // must be before TRISET_HH to ensure correct order #ifndef TRISET_HH #define TRISET_HH #include "amma/RCHandleA.hh" #include "amma/SArray1d.hh" #include "amma/Vector3d.hh" #include "amma/Filename.hh" #ifndef AMMASUB #include "amma/Plan3PVV.hh" #include "amma/MeanCo3d.hh" #include "amma/Polops.hh" #endif #include class BodyCTriSetC; //: A simple mesh class // Set of triangles: list of 3D vertex + list of TriC //============================================================ // NB: TriC contains pointers to BodyTriSetC & therefore cannot be assigned // without either (1) Explicit change of pointers or (2) ref count class BodyTriSetC : public BodyRefCounterVC { public: //--------------------------------------------- Constructors BodyTriSetC(); BodyTriSetC(FilenameC name); // load file in .tri format // (triangles only, index 0..N-1) #ifndef AMMASUB BodyTriSetC(SArray1dC v,SArray1dC e); // construct from an array of verticies 'v' & elements 'e' #endif BodyTriSetC(const IntT nvertex,const IntT nelement); // construct empty/uninitialised // use PutVertex()/PutElement() to initialise... #ifndef AMMASUB BodyTriSetC(const PolopsC& polys); #endif virtual BodyRefCounterVC &Copy() const; //: new physical copy BodyTriSetC(const BodyTriSetC& tris); public: //-------------------------------------------- Load Empty void PutVertex(const IndexT iIndex,const Vector3dC v) {vertex[iIndex]=v;} void PutElement(const IndexT iIndex,const TriC t) { //TriC tri(t); //tri.SetBodyTriSet(*this); // guarantee reference is correct !!! element[iIndex]=t; } //--------------------------------------------- Access IntT NumVertex() const {return vertex.Size();} IntT NumElement() const {return element.Size();} Vector3dC Vertex(const IndexT iIndex) const { return vertex[iIndex]; } Vector3dC& Vertex(const IndexT iIndex) { return vertex[iIndex]; } const TriC& Element(const IndexT iIndex) const { return element[iIndex];} TriC& Element(const IndexT iIndex) { return element[iIndex];} // access i^th element TriC* PElement(const IndexT iIndex) {return &element[iIndex];} // CAUTION - not ref counted //--------------------------------------------- Operations void Save(FilenameC name); // save to file 'name' in .tri format void SaveVRML(FilenameC filename); // save vrml 2 format (geometry only) #ifndef AMMASUB PlanePVV3dC FitPlane(); // Best fit plane through data // - 1st two eigenvectors of vertex covariance matrix #endif RealT Length(const IntT i1, const IntT i2) {return Vertex(i1).EuclidDistance(Vertex(i2));} RealT AverageEdgeLength(); RealT MinimumEdgeLength(); Vector3dC AverageNormal(); // average element normal Vector3dC VertexNormal(const IndexT iIndex); // return vertex normal // (setup an internal array of vertex normals) Vector3dC SurfaceNormal(RealT dAlpha, RealT dBeta, IndexT iElement); //: Return an interpolated surface normal // dAlpha and dBeta are barycentric coordinates of a point on iElement. // The returned vector is the interpolated normal at this point. void Limits(Vector3dC& xmin, Vector3dC& xmax); // bounding volume in 3D BooleanT IsSetupBound() const {return setup_bound;} // returns setup status of bound void SetupBound(); // Setup boundary information for each TriC Element // (call in constructor) PolopsC ExportPolops() const; protected: SArray1dC vertex; SArray1dC element; private: //BodyTriSetC(const BodyTriSetC &oth) // { assert(0); } //SArray1dC vertex; //SArray1dC element; //------------------------------------------------ Vector3dC* VertexP(const IndexT iIndex) {return &vertex[iIndex];} //----------------------------------------------- Vertex Normal SArray1dC vertex_normal; // empty by default void SetupVertexNormal(); //------------------------------------------------ IntT LoadTri(FilenameC fname); void SaveTri(FilenameC fname); //------------------------------------------------ BooleanT setup_bound; // Bound element labelling setup/not setup status //------------------------------------------------ friend ostream & operator<<(ostream & s, const BodyTriSetC & t); }; //============================================================ //: A simple mesh class // Set of triangles: list of 3D vertex + list of TriC class TriSetC : public RCHandleAC { public: TriSetC() {} //: Constructor. // empty triset TriSetC(const IntT nvertex,const IntT nelement) : RCHandleAC(* new BodyTriSetC(nvertex,nelement)) {} // create an empty TriSetC with space allocated // to put 'nvertex' verticies and 'nelement' triangles TriSetC(FilenameC filename) : RCHandleAC(* new BodyTriSetC(filename)) {} // load file in .tri format // (triangles only, index 0..N-1) TriSetC(SArray1dC v,SArray1dC e) : RCHandleAC(* new BodyTriSetC(v,e)) {} //: Construct from an array of vectors and one of tri's. TriSetC(const PolopsC &Oth) : RCHandleAC(* new BodyTriSetC(Oth)) {} //: Construct from Polops. protected: TriSetC(BodyTriSetC &bod) : RCHandleAC(bod) {} //: Body contructor. inline BodyTriSetC& TriSetC::Body() { return static_cast(RCHandleAC::Body()); } //: Access body. // This isn't really needed, they're just to ensure // all derived classes work properly. inline const BodyTriSetC& TriSetC::Body() const { return static_cast(RCHandleAC::Body()); } //: Access body (for constant handle) public: TriSetC Copy() const {return TriSetC(static_cast(Body().Copy()));} //: new physical copy //-------------------------------------------- Load Empty void PutVertex(const IndexT iIndex,const Vector3dC v) {Body().PutVertex(iIndex,v);} //: Put a vertex into structure. void PutElement(const IndexT iIndex,const TriC t) { TriC tri(t); tri.SetBodyTriSet(Body()); // guarantee reference is correct !!! Body().PutElement(iIndex,tri); } //: Put an element into structure. //--------------------------------------------- Access IntT NumVertex() const {return Body().NumVertex();} //: Access the number of vertices in the TriSet IntT NumElement() const {return Body().NumElement();} //: Access the number of triangles in the TriSet Vector3dC& Vertex(const IndexT iIndex) {return Body().Vertex(iIndex);} //: Access to a particular vertex position Vector3dC Vertex(const IndexT iIndex) const {return Body().Vertex(iIndex);} //: Const access to a particular vertex position const TriC& Element(const IntT iIndex) const {return Body().Element(iIndex);} //TriC& Element(const IntT index); does not guarantee pointers // access i^th element TriC& Element(const IndexT iIndex) {return Body().Element(iIndex);} TriC* PElement(const IndexT iIndex) {return Body().PElement(iIndex);} // pointer to ith element // CAUTION - should return ref counter iterator... use in TriSet3to2 //--------------------------------------------- Operations void Save(FilenameC filename) {Body().Save(filename);} // save to file 'name' in .tri format void SaveVRML(FilenameC filename) {Body().SaveVRML(filename);} // save vrml 2 format (geometry only) RealT Length(const IntT i1, const IntT i2) {return Body().Length(i1,i2);} RealT AverageEdgeLength() {return Body().AverageEdgeLength();} RealT MinimumEdgeLength() {return Body().MinimumEdgeLength();} void ConstrainEdgeLength(const RealT maximum_edge_length); // constrain the edge lenght of this triset to 'maximum_edge_length' void ConstrainNormals(const Vector3dC common_normal); // constrain all element normals to be in orientation as 'common_normal' // ie not >90 to common_normal Vector3dC AverageNormal() {return Body().AverageNormal();} // average element normal Vector3dC VertexNormal(const IndexT iIndex) {return Body().VertexNormal(iIndex);} // return vertex normal // (setup an internal array of vertex normals) Vector3dC SurfaceNormal(RealT dAlpha, RealT dBeta, IndexT iElement) {return Body().SurfaceNormal(dAlpha,dBeta,iElement);} //: Return an interpolated surface normal // dAlpha and dBeta are barycentric coordinates of a point on iElement. // The returned vector is the interpolated normal at this point. void Limits(Vector3dC& xmin, Vector3dC& xmax) {Body().Limits(xmin,xmax);} // bounding volume in 3D BooleanT IsSetupBound() const {return Body().IsSetupBound();} // returns setup status of bound void SetupBound() {return Body().SetupBound();} // Setup boundary information for each TriC Element // (call in constructor) void Transform(RigidTransC& transform); // Rigid transform of all verticies Vector3dC Centroid(); // Centre of triset // - average vertex position void TransformAboutCentroid(RigidTransC& transform); // Rigid transform of all verticies - for rotation about centroid // i) triset is translated so that centroid = origin // ii) transform is applied // iii) inverse of step (i) is applied inline PolopsC ExportPolops() const {return Body().ExportPolops();} //: Export to polops. friend ostream & operator<<(ostream & s, const BodyTriSetC & t); friend class CTriSetC; }; //-------------------------------------------------------------------- // output external to class (ie only public access) ostream & operator<<(ostream & s, const TriSetC & t); //: Output triset to a stream. istream & operator>>(istream & s, const TriSetC & t); //: Input triset from a stream. ostream & operator<<(ostream & s, const BodyTriSetC & t); // Saves the list into the output stream. //-------------------------------------------------------------------- #endif