-
Notifications
You must be signed in to change notification settings - Fork 9
Description
Remus isn't the place to build, modify, or query a mesh, what it is designed to do is send a mesh to another process/computer/thread. Because of this the mesh class(es) in Remus can have a well defined structure that is easy for any library/program to copy into, or specify where the allocated data already is.
Now for an initial implementation of this I don't want to be super fancy and allow arbitrary mappings of any pre-existing, instead I want to use a very simple model of a mesh with the following rules:
- A mesh can only have a single collection of points
- Points can be either 2 or 3 dimensional
- Points can be either float or doubles
- The layout of the point coordinates are in a linear array with the following order:
x1,y1,z1,x2,y2,z2,... - A mesh can have any number of Cell Collections
- A Cell Collection can only contain a single cell type
- We support the following cell types
- vertex
- line
- triangle
- tetrahedron
- hexahedron
- Cell Connection values can either be int32 or int64
So a simple schema for a mesh of triangles and lines could look like:
{
"points" : { "dims" : 3, "num_elements": "300",
"data_type": "float", "data" : [ x1, y1, z1, x2, y2, z2, .... ]
}
"cells" : [
{ "cell_type" : "triangle", "num_cells": 400,
"data_type": "int32", "data" : [ a1, a2, a3, b1, b2, b3, c1, c2, c3, ...]
},
{ "cell_type" : "line", "num_cells": 50,
"data_type": "int32", "data" : [ a1, a2, b1, b2, c1, c2, ...]
}
]
}
This will allow us to be easily able to serialize and deserialize the data as a little endian encoded binary blob.
Now that we understand the schema of the mesh classes lets see how this
would look how we could write the interface with a couple simple C++ classes that can reference pre-existing allocated memory, or be easily copied into. Note that none of these classes show how to serialize to and from them, as those would be similar to how remus::proto::JobContent and remus::proto::JobRequirements.
namespace remus { namespace mesh {
class Points
{
public:
enum DataType { FLOAT=4, DOUBLE=8 };
enum Dimensionality { Dim2D, Dim3D };
//Use existing memory, we don't deallocate passed in memory
//Pointer must be valid as long as this class exists
Points(double* existing_coordinates, std::size_t numPoints, Dimensionality dim);
//Use existing memory, we don't deallocate passed in memory
//Pointer must be valid as long as this class exists
Points(float* existing_coordinates, std::size_t numPoints, Dimensionality dim);
//Pass in arbitrary iterators and copy the data into memory that we will allocate.
//Iterators must support std::iterator_traits, and have a value_type
//of either float or double
//Iterators only have to be valid for the initial construction of the object.
template<typename T>
Points(T begin, T end, std::size_t numPoints, Dimensionality dim);
//returns the current dimension of the points
Dimensionality dims() const;
//returns true if the type of the points is float
bool isFloat() const;
//returns true if the type of the points is double
bool isDouble() const;
//returns the data type of the points, note that the DataType enum value is also the sizeof of the datatype.
DataType dataType();
//returns the number of points
std::size_t numPoints() const;
//returns a pointer initialized to the first element of the data
const char* begin() const;
//returns a pointer initialized to first element past the end of the data.
const char* end() const;
private:
class InternalImpl;
boost::shared_ptr<InternalImpl> Implementation;
};
class Cells
{
public:
enum DataType { Int32=4, Int64=8 };
enum Types { Vertex,Line,Triangle,Tetrahedron,Hexahedron };
//Use existing memory, we don't deallocate passed in memory
//Pointer must be valid as long as this class exists
Cells(std::int32_t* existing_cells, std::size_t numCells, Types type);
//Use existing memory, we don't deallocate passed in memory
//Pointer must be valid as long as this class exists
Cells(std::int64_t* existing_cells, std::size_t numCells, Types type);
//Pass in arbitrary iterators and copy the data into memory that we will allocate.
//Iterators must support std::iterator_traits, and have a value_type
//of either int32 or int64
//Iterators only have to be valid for the initial construction of the object.
template<typename T>
Cells(T begin, T end, std::size_t numCells, Types type);
//returns the cell type we are holding
Types cellType() const;
//returns true if the type is int32
bool isInt32() const;
//returns true if the type is int64
bool isInt64() const;
//returns the data type of the points, note that the DataType enum value is also the sizeof of the datatype.
DataType dataType();
//returns the number of cells
std::size_t numCells() const;
//returns a pointer initialized to the first element of the data
const char* begin() const;
//returns a pointer initialized to first element past the end of the data.
const char* end() const;
private:
class InternalImpl;
boost::shared_ptr<InternalImpl> Implementation;
};
class Mesh
{
typedef std::vector<Cells>::const_iterator const_iterator;
public:
Mesh(Points p, Cells c):
PointData(p),
CellsCollection(1,c)
{
}
Mesh(Points p, std::vector<Cells> c):
PointData(p),
CellsCollection(c)
{
}
//returns a read only reference to the underlying points object.
const Points& points( ) const;
//returns the number of cells
std::size_t numCellCollections() const;
//total sum of cells in all the collections
std::size_t totalNumCells() const;
//return a read only reference of the cells at a given index inside the collection
const Cells& cells( std::size_t index) const;
//returns an iterator initialized to the first element of the cells collection
const_iterator begin() const;
//returns an iterator initialized to first element past the end of the cells collection.
const_iterator end() const;
private:
Points PointData;
std::vector<Cells> CellsCollection;
};
} }