Commit 27cbe3d9 authored by Dave Moxey's avatar Dave Moxey
Browse files

Merge branch 'feature/cad_factory' into 'master'

feature/cadsystem_factories

This merge takes the existing OCE cad engine and turns it into a more general system where OCE is the default backend.
This is in preparation of CFI and other installation dependant backends being added.
All tests pass (these are not on buildbot yet).

See merge request !676
parents dc770c73 81c0fff3
......@@ -48,6 +48,7 @@ v4.4.0
mesh (!669)
- Improvements to mesh linearisation module (!659)
- Add support for Gmsh high-order output (!679)
- Move CAD classes to factory format (!676)
- Add option to `linearise` module to linearise only prisms (!688)
**FieldConvert:**
......
......@@ -15,7 +15,7 @@ IF(NEKTAR_USE_MESHGEN)
ELSE()
SET(BUILD_OCC ON)
ENDIF()
OPTION(THIRDPARTY_BUILD_OCC "Build OpenCascade library from ThirdParty."
${BUILD_OCC})
......@@ -33,7 +33,7 @@ IF(NEKTAR_USE_MESHGEN)
IF(WIN32)
MESSAGE(SEND_ERROR "Cannot currently use OpenCascade with Nektar++ on Windows")
ENDIF()
EXTERNALPROJECT_ADD(
opencascade-6.9
PREFIX ${TPSRC}
......
......@@ -36,13 +36,6 @@
#ifndef NEKMESHUTILS_CADSYSTEM_CADCURVE
#define NEKMESHUTILS_CADSYSTEM_CADCURVE
#include <boost/shared_ptr.hpp>
#include <LibUtilities/BasicUtils/SharedArray.hpp>
#include <LibUtilities/Memory/NekMemoryManager.hpp>
#include <NekMeshUtils/CADSystem/OpenCascade.h>
#include <NekMeshUtils/CADSystem/CADObj.h>
#include <NekMeshUtils/CADSystem/CADVert.h>
#include <NekMeshUtils/CADSystem/CADSurf.h>
......@@ -53,10 +46,8 @@ namespace NekMeshUtils
{
/**
* @brief class for CAD curves.
* @brief base class for CAD curves.
*
* This class wraps the OpenCascade BRepAdaptor_Curve class for use with
* Nektar++.
*/
class CADCurve : public CADObj
{
......@@ -66,16 +57,18 @@ public:
/**
* @brief Default constructor.
*/
CADCurve(int i, TopoDS_Shape in);
CADCurve(){};
~CADCurve(){};
~CADCurve()
{
}
/**
* @brief Returns the minimum and maximum parametric coords t of the curve.
*
* @return Array of two entries, min and max parametric coordinate.
*/
Array<OneD, NekDouble> Bounds();
virtual Array<OneD, NekDouble> Bounds() = 0;
/**
* @brief Calculates the arclength between the two paremetric points \p ti
......@@ -85,7 +78,7 @@ public:
* @param tf Second parametric coordinate.
* @return Arc length between \p ti and \p tf.
*/
NekDouble Length(NekDouble ti, NekDouble tf);
virtual NekDouble Length(NekDouble ti, NekDouble tf) = 0;
/**
* @brief Gets the location (x,y,z) in an array out of the curve at
......@@ -94,12 +87,12 @@ public:
* @param t Parametric coordinate
* @return Array of x,y,z
*/
Array<OneD, NekDouble> P(NekDouble t);
virtual Array<OneD, NekDouble> P(NekDouble t) = 0;
/**
* @brief Gets the second derivatives at t
*/
Array<OneD, NekDouble> D2(NekDouble t);
virtual Array<OneD, NekDouble> D2(NekDouble t) = 0;
/**
* @brief Calculates the parametric coordinate and arclength location
......@@ -110,28 +103,34 @@ public:
*
* @todo This really needs improving for accuracy.
*/
NekDouble tAtArcLength(NekDouble s);
virtual NekDouble tAtArcLength(NekDouble s) = 0;
/**
* @brief Gets the start and end of the curve.
*
* @return Array with 6 entries of endpoints x1,y1,z1,x2,y2,z2.
*/
Array<OneD, NekDouble> GetMinMax();
virtual Array<OneD, NekDouble> GetMinMax() = 0;
/// set the ids of the surfaces either side of the curve
/**
* @brief set the ids of the surfaces either side of the curve
*/
void SetAdjSurf(std::vector<CADSurfSharedPtr> i)
{
m_adjSurfs = i;
}
/// returns the ids of neigbouring surfaces
/*
* @brief returns the ids of neigbouring surfaces
*/
std::vector<CADSurfSharedPtr> GetAdjSurf()
{
return m_adjSurfs;
}
/// returns lenght of the curve
/*
* @brief returns lenght of the curve
*/
NekDouble GetTotLength()
{
return m_length;
......@@ -145,18 +144,16 @@ public:
m_mainVerts = falVert;
}
/// get the ids of the vertices that are the ends of the curve,
/// which are in the main cad list
/*
* @brief get the vertices that are the ends of the curve,
* which are in the main cad list
*/
std::vector<CADVertSharedPtr> GetVertex()
{
return m_mainVerts;
}
private:
/// OpenCascade object of the curve.
BRepAdaptor_Curve m_occCurve;
/// OpenCascade edge
TopoDS_Edge m_occEdge;
protected:
/// Length of edge
NekDouble m_length;
/// List of surfaces which this curve belongs to.
......@@ -166,6 +163,11 @@ private:
};
typedef boost::shared_ptr<CADCurve> CADCurveSharedPtr;
typedef LibUtilities::NekFactory<std::string, CADCurve> CADCurveFactory;
CADCurveFactory& GetCADCurveFactory();
}
}
......
......@@ -39,7 +39,6 @@
#include <boost/shared_ptr.hpp>
#include <LibUtilities/Memory/NekMemoryManager.hpp>
#include <NekMeshUtils/CADSystem/OpenCascade.h>
namespace Nektar
{
......@@ -53,12 +52,6 @@ enum cadType
surf
};
/**
* @brief class for CAD curves.
*
* This class wraps the OpenCascade BRepAdaptor_Curve class for use with
* Nektar++.
*/
class CADObj
{
public:
......
......@@ -36,14 +36,9 @@
#ifndef NekMeshUtils_CADSYSTEM_CADSURF
#define NekMeshUtils_CADSYSTEM_CADSURF
#include <boost/shared_ptr.hpp>
#include <LibUtilities/BasicUtils/SharedArray.hpp>
#include <LibUtilities/Memory/NekMemoryManager.hpp>
#include <NekMeshUtils/CADSystem/OpenCascade.h>
#include <NekMeshUtils/CADSystem/CADObj.h>
#include <NekMeshUtils/CADSystem/CADVert.h>
#include <NekMeshUtils/CADSystem/CADSystem.h>
namespace Nektar
{
......@@ -54,19 +49,7 @@ class CADCurve;
typedef boost::shared_ptr<CADCurve> CADCurveSharedPtr;
/**
* @brief struct which descibes a collection of cad edges which for a
* loop on the cad surface
*/
struct EdgeLoop
{
std::vector<CADCurveSharedPtr> edges;
std::vector<int> edgeo; //0 is forward 1 is backward
Array<OneD, NekDouble> center;
NekDouble area;
};
/**
* @brief class for handleing a cad surface
* @brief base class for a cad surface
*/
class CADSurf : public CADObj
......@@ -77,18 +60,16 @@ public:
/**
* @brief Default constructor.
*/
CADSurf(int i, TopoDS_Shape in, std::vector<EdgeLoop> ein);
CADSurf()
{
}
~CADSurf(){};
~CADSurf()
{
}
/**
* @brief Get the IDs of the edges which bound the surface.
*
* The edges are organsised into two vectors, which are grouped into the
* continuous loops of the bounding edges, then the edges, which are a
* pair of integers. The first item is the edge ID and the second is an
* integer that indicates whether this edge is orientated forwards or
* backwards on this surface to form the loop.
* @brief Get the loop structures which bound the cad surface
*/
std::vector<EdgeLoop> GetEdges()
{
......@@ -100,17 +81,7 @@ public:
*
* @return Array of 4 entries with parametric umin,umax,vmin,vmax.
*/
Array<OneD, NekDouble> GetBounds()
{
Array<OneD,NekDouble> b(4);
b[0] = m_occSurface.FirstUParameter();
b[1] = m_occSurface.LastUParameter();
b[2] = m_occSurface.FirstVParameter();
b[3] = m_occSurface.LastVParameter();
return b;
}
virtual Array<OneD, NekDouble> GetBounds() = 0;
/**
* @brief Get the normal vector at parametric point u,v.
......@@ -118,7 +89,7 @@ public:
* @param uv Array of u and v parametric coords.
* @return Array of xyz components of normal vector.
*/
Array<OneD, NekDouble> N (Array<OneD, NekDouble> uv);
virtual Array<OneD, NekDouble> N (Array<OneD, NekDouble> uv) = 0;
/**
* @brief Get the set of first derivatives at parametric point u,v
......@@ -126,7 +97,7 @@ public:
* @param uv Array of u and v parametric coords.
* @return Array of xyz copmonents of first derivatives.
*/
Array<OneD, NekDouble> D1 (Array<OneD, NekDouble> uv);
virtual Array<OneD, NekDouble> D1 (Array<OneD, NekDouble> uv) = 0;
/**
* @brief Get the set of second derivatives at parametric point u,v
......@@ -134,7 +105,7 @@ public:
* @param uv array of u and v parametric coords
* @return array of xyz copmonents of second derivatives
*/
Array<OneD, NekDouble> D2 (Array<OneD, NekDouble> uv);
virtual Array<OneD, NekDouble> D2 (Array<OneD, NekDouble> uv) = 0;
/**
* @brief Get the x,y,z at parametric point u,v.
......@@ -142,7 +113,7 @@ public:
* @param uv Array of u and v parametric coords.
* @return Array of xyz location.
*/
Array<OneD, NekDouble> P (Array<OneD, NekDouble> uv);
virtual Array<OneD, NekDouble> P (Array<OneD, NekDouble> uv) = 0;
/**
* @brief Performs a reverse look up to find u,v and x,y,z.
......@@ -150,12 +121,25 @@ public:
* @param p Array of xyz location
* @return The parametric location of xyz on this surface
*/
Array<OneD, NekDouble> locuv(Array<OneD, NekDouble> p);
virtual Array<OneD, NekDouble> locuv(Array<OneD, NekDouble> p) = 0;
/**
* @brief does unconstrained locuv to project point from anywhere
* and calculate the distance between the orthonormal projection to the surface
* and the point
*/
virtual NekDouble DistanceTo(Array<OneD, NekDouble> p) = 0;
/**
* @brief takes a point from anywhere find the nearest surface point and its
* uv
*/
virtual void ProjectTo(Array<OneD, NekDouble> &tp, Array<OneD, NekDouble> &uv) = 0;
/**
* @brief returns true if the surface is flat (2D)
* @brief returns curvature at point uv
*/
bool IsPlane();
virtual NekDouble Curvature(Array<OneD, NekDouble> uv) = 0;
/**
* @brief sets the flag to reverse the normal for this suface,
......@@ -167,55 +151,30 @@ public:
m_correctNormal = false;
}
bool IsReversedNormal()
{
return !m_correctNormal;
}
/**
* @brief surface needs to know if it is bounded by only two curves
* @brief query reversed normal
*/
void SetTwoC()
bool IsReversedNormal()
{
m_hasTwoCurves = true;
return !m_correctNormal;
}
/**
* @brief query two curves
*/
bool GetTwoC(){return m_hasTwoCurves;}
/**
* @brief does unconstrained locuv to project point from anywhere
*/
NekDouble DistanceTo(Array<OneD, NekDouble> p);
void ProjectTo(Array<OneD, NekDouble> &tp, Array<OneD, NekDouble> &uv);
/**
* @brief returns curvature at point uv
*/
NekDouble Curvature(Array<OneD, NekDouble> uv);
private:
/// Function which tests the the value of uv used is within the surface
void Test(Array<OneD, NekDouble> uv);
protected:
/// normal
bool m_correctNormal;
/// flag to alert the mesh generation to a potential problem is both
/// curves have only two points in the mesh
bool m_hasTwoCurves;
/// OpenCascade object for surface.
BRepAdaptor_Surface m_occSurface;
/// Alternate OpenCascade object for surface. Used by reverse lookup.
Handle(Geom_Surface) m_s;
/// List of bounding edges in loops with orientation.
std::vector<EdgeLoop> m_edges;
/// Function which tests the the value of uv used is within the surface
virtual void Test(Array<OneD, NekDouble> uv) = 0;
};
typedef boost::shared_ptr<CADSurf> CADSurfSharedPtr;
typedef LibUtilities::NekFactory<std::string, CADSurf> CADSurfFactory;
CADSurfFactory& GetCADSurfFactory();
}
}
......
......@@ -33,11 +33,7 @@
//
////////////////////////////////////////////////////////////////////////////////
#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
#include <NekMeshUtils/CADSystem/CADSystem.h>
#include <NekMeshUtils/CADSystem/CADObj.h>
#include <NekMeshUtils/CADSystem/CADVert.h>
#include <NekMeshUtils/CADSystem/CADCurve.h>
#include <NekMeshUtils/CADSystem/CADSurf.h>
......@@ -49,414 +45,37 @@ namespace Nektar
namespace NekMeshUtils
{
string CADSystem::GetName()
{
return m_name;
}
void CADSystem::Report()
{
cout << endl << "CAD report:" << endl;
cout << "\tCAD has: " << m_curves.size() << " curves." << endl;
cout << "\tCAD has: " << m_surfs.size() << " surfaces." << endl;
}
Array<OneD, NekDouble> CADSystem::GetBoundingBox()
{
Array<OneD, NekDouble> bound(6);
bound[0] = numeric_limits<double>::max(); // xmin
bound[1] = numeric_limits<double>::min(); // xmax
bound[2] = numeric_limits<double>::max(); // ymin
bound[3] = numeric_limits<double>::min(); // ymax
bound[4] = numeric_limits<double>::max(); // zmin
bound[5] = numeric_limits<double>::min(); // zmax
for (int i = 1; i <= m_curves.size(); i++)
{
CADCurveSharedPtr c = GetCurve(i);
Array<OneD, NekDouble> ends = c->GetMinMax();
bound[0] = min(bound[0], min(ends[0], ends[3]));
bound[1] = max(bound[1], max(ends[0], ends[3]));
bound[2] = min(bound[2], min(ends[1], ends[4]));
bound[3] = max(bound[3], max(ends[1], ends[4]));
bound[4] = min(bound[4], min(ends[2], ends[5]));
bound[5] = max(bound[5], max(ends[2], ends[5]));
}
return bound;
}
vector<int> CADSystem::GetBoundarySurfs()
{
vector<int> ret;
set<int> surfs;
vector<CADCurveSharedPtr> cs;
Array<OneD, NekDouble> bound = GetBoundingBox();
for (int i = 1; i <= m_curves.size(); i++)
{
CADCurveSharedPtr c = GetCurve(i);
Array<OneD, NekDouble> ends = c->GetMinMax();
if((fabs(bound[0] - ends[0]) < 1e-4 ||
fabs(bound[0] - ends[3]) < 1e-4 ||
fabs(bound[1] - ends[0]) < 1e-4 ||
fabs(bound[1] - ends[3]) < 1e-4)
&&
(fabs(bound[2] - ends[1]) < 1e-4 ||
fabs(bound[2] - ends[4]) < 1e-4 ||
fabs(bound[3] - ends[1]) < 1e-4 ||
fabs(bound[3] - ends[4]) < 1e-4)
&&
(fabs(bound[4] - ends[2]) < 1e-4 ||
fabs(bound[4] - ends[5]) < 1e-4 ||
fabs(bound[5] - ends[2]) < 1e-4 ||
fabs(bound[5] - ends[5]) < 1e-4) )
{
//curve touches on bounding box
cs.push_back(c);
}
}
for(int i = 0; i < cs.size(); i++)
{
vector<CADSurfSharedPtr> s = cs[i]->GetAdjSurf();
for(int j = 0; j < s.size(); j++)
{
surfs.insert(s[j]->GetId());
}
}
set<int>::iterator it;
for(it = surfs.begin(); it != surfs.end(); it++)
{
ret.push_back(*it);
}
return ret;
}
bool CADSystem::LoadCAD()
EngineFactory& GetEngineFactory()
{
if (!boost::filesystem::exists(m_name.c_str()))
{
return false;
}
string ext;
size_t pos = m_name.find(".");
ext = m_name.substr(pos);
if (boost::iequals(ext, ".STEP") || boost::iequals(ext, ".STP"))
{
// Takes step file and makes OpenCascade shape
STEPControl_Reader reader;
reader = STEPControl_Reader();
reader.ReadFile(m_name.c_str());
reader.NbRootsForTransfer();
reader.TransferRoots();
shape = reader.OneShape();
if (shape.IsNull())
{
return false;
}
}
else if (boost::iequals(ext, ".IGES") || boost::iequals(ext, ".IGS"))
{
// Takes IGES file and makes OpenCascade shape
IGESControl_Reader reader;
reader = IGESControl_Reader();
reader.ReadFile(m_name.c_str());
reader.NbRootsForTransfer();
reader.TransferRoots();
shape = reader.OneShape();
if (shape.IsNull())
{
return false;
}
}
else
{
return false;
}
// faces and verts can be extracted straight from shape
TopTools_IndexedMapOfShape mapOfVerts, mapOfFaces;
TopExp::MapShapes(shape, TopAbs_VERTEX, mapOfVerts);
TopExp::MapShapes(shape, TopAbs_FACE, mapOfFaces);
// edges need to be built from loops around faces to elimiate degen and
// hanging edges
TopTools_IndexedMapOfShape mapOfEdges;
// build map of verticies
for (int i = 1; i <= mapOfVerts.Extent(); i++)
{
TopoDS_Shape v = mapOfVerts.FindKey(i);
AddVert(i, v);
}
// For each face of the geometry, get the local edges which bound it. If
// they are valid (their type != 7), then add them to an edge map. This
// filters out the dummy edges which OCC uses.
for (int i = 1; i <= mapOfFaces.Extent(); i++)
{
TopoDS_Shape face = mapOfFaces.FindKey(i);
TopTools_IndexedMapOfShape localEdges;
TopExp::MapShapes(face, TopAbs_EDGE, localEdges);
for (int j = 1; j <= localEdges.Extent(); j++)
{
TopoDS_Shape edge = localEdges.FindKey(j);
BRepAdaptor_Curve curve = BRepAdaptor_Curve(TopoDS::Edge(edge));
if (curve.GetType() != 7)
{
if (!(mapOfEdges.Contains(edge)))
{
mapOfEdges.Add(edge);
}
}
}
}
map<int, vector<int> > adjsurfmap; // from id of curve to list of ids of
// surfs
// Adds edges to our type and map
for (int i = 1; i <= mapOfEdges.Extent(); i++)
{
TopoDS_Shape edge = mapOfEdges.FindKey(i);
TopoDS_Vertex fv =
TopExp::FirstVertex(TopoDS::Edge(edge), Standard_True);
TopoDS_Vertex lv =
TopExp::LastVertex(TopoDS::Edge(edge), Standard_True);
if (edge.Orientation() == 0)
{
AddCurve(i, edge, mapOfVerts.FindIndex(fv),