I am using a data model with classes: Point2D, Point3D, PointGeo:
template <class T>
class Point2D
{
protected:
T x;
T y;
...
};
template <class T>
class Point3D
{
protected:
T x;
T y;
T z;
...
};
template <class T>
class PointGeo
{
protected:
T lat;
T lon;
...
};
To manage instances of these classes the folowing classes allowing loading points from file, adding/removing points, clearing list, printing are used...
List of 2D points
template <class T>
struct TPoints2DList
{
typedef std::vector <Point2D <T> > Type;
};
template <class T>
class Points2DList
{
private:
typename TPoints2DList <T>::Type points;
public:
Points2DList() : points ( 0 ) {}
virtual ~Points2DList() {points.clear();}
Points2DList ( const Points2DList &source );
typename TPoints2DList <T>::Type ::iterator begin() { return points.begin(); }
typename TPoints2DList <T>::Type::const_iterator begin() const { return points.begin(); }
typename TPoints2DList <T>::Type::iterator end() { return points.end(); }
typename TPoints2DList <T>::Type::const_iterator end() const { return points.end(); }
Point2D <T> &operator [] ( int index ) {return points[index];}
const Point2D <T> &operator [] ( int index ) const {return points[index];}
public:
//Overloaded member functions
inline void clear() {points.clear();};
inline void pop_back() {points.pop_back();}
inline void push_back ( Point2D <T> p ) { points.push_back ( p );}
inline unsigned int size() const {return points.size();}
public:
//Other methods
void loadPointsFromFile ( const char *file);
...
}
List of 3D points
template <class T>
struct TPoints3DList
{
typedef std::vector <Point3D <T> > Type;
};
template <class T>
class Points3DList
{
private:
typename TPoints3DList <T>::Type points;
public:
Points3DList() : points ( 0 ) {}
virtual ~Points2DList() {points.clear();}
Points3DList ( const Points3DList &source );
typename TPoints3DList <T>::Type ::iterator begin() { return points.begin(); }
typename TPoints3DList <T>::Type::const_iterator begin() const { return points.begin(); }
typename TPoints3DList <T>::Type::iterator end() { return points.end(); }
typename TPoints3DList <T>::Type::const_iterator end() const { return points.end(); }
Point3D <T> &operator [] ( int index ) {return points[index];}
const Point3D <T> &operator [] ( int index ) const {return points[index];}
public:
inline void clear() {points.clear();};
inline void pop_back() {points.pop_back();}
inline void push_back ( Point3D <T> p ) { points.push_back ( p );}
inline unsigned int size() const {return points.size();}
public:
//Other methods
void loadPointsFromFile ( const char *file);
...
}
Source code of PointGeo class is similar...
So differences in the code between the classes are small. They differ in methods for loading, printing, saving data.
Would it be inappropriate to design a class replacing all three classes? How to create methods for loading, printing data specific for the data type?
The similar situation occurs for the dynamic alocation: Node2D, Node3D,... classes. Class Node2D stores some topological relationships and using pointers to other nodes or faces... In such case all three classes will have a different destructor...
List of 2D points
template <class T>
struct TNodes2DList
{
typedef std::vector <Node2D <T> *> Type;
};
Thank you very much for your comments and suggestions. I am writing geometric library and thinking about the most suitable data model.