netgen/libsrc/occ/occgeom.hpp
2021-11-11 10:04:39 +01:00

656 lines
20 KiB
C++

#ifndef FILE_OCCGEOM
#define FILE_OCCGEOM
/* *************************************************************************/
/* File: occgeom.hpp */
/* Author: Robert Gaisbauer */
/* Date: 26. May 03 */
/* *************************************************************************/
#ifdef OCCGEOMETRY
#include <meshing.hpp>
#include <Standard_Version.hxx>
#include "BRep_Tool.hxx"
#include "Geom_Curve.hxx"
#include "Geom2d_Curve.hxx"
#include "Geom_Surface.hxx"
#include "GeomAPI_ProjectPointOnSurf.hxx"
#include "GeomAPI_ProjectPointOnCurve.hxx"
#include "BRepTools.hxx"
#include "TopExp.hxx"
#include "BRepBuilderAPI_MakeVertex.hxx"
#include "BRepBuilderAPI_MakeShell.hxx"
#include "BRepBuilderAPI_MakeSolid.hxx"
#include "BRepOffsetAPI_Sewing.hxx"
#include "BRepLProp_SLProps.hxx"
#include "BRepAdaptor_Surface.hxx"
#include "Poly_Triangulation.hxx"
#include "Poly_Array1OfTriangle.hxx"
#include "TColgp_Array1OfPnt2d.hxx"
#include "Poly_Triangle.hxx"
#include "GProp_GProps.hxx"
#include "BRepGProp.hxx"
#include "gp_Pnt.hxx"
#include "TopoDS.hxx"
#include "TopoDS_Solid.hxx"
#include "TopExp_Explorer.hxx"
#include "TopTools_ListIteratorOfListOfShape.hxx"
#include "TopoDS_Wire.hxx"
#include "BRepTools_WireExplorer.hxx"
#include "TopTools_IndexedMapOfShape.hxx"
#include "BRepLProp_CLProps.hxx"
#include "BRepAdaptor_Curve.hxx"
#include "TopoDS_Shape.hxx"
#include "TopoDS_Face.hxx"
#include "IGESToBRep_Reader.hxx"
#include "Interface_Static.hxx"
#include "GeomAPI_ExtremaCurveCurve.hxx"
#include "Standard_ErrorHandler.hxx"
#include "Standard_Failure.hxx"
#include "ShapeUpgrade_ShellSewing.hxx"
#include "ShapeFix_Shape.hxx"
#include "ShapeFix_Wireframe.hxx"
#include "BRepMesh_IncrementalMesh.hxx"
#include "BRepBndLib.hxx"
#include "Bnd_Box.hxx"
#include "ShapeAnalysis.hxx"
#include "ShapeBuild_ReShape.hxx"
#include "BOPAlgo_Builder.hxx"
// Philippose - 29/01/2009
// OpenCascade XDE Support
// Include support for OpenCascade XDE Features
#include "TDocStd_Document.hxx"
#include "Quantity_Color.hxx"
#include "XCAFApp_Application.hxx"
#include "XCAFDoc_ShapeTool.hxx"
#include "XCAFDoc_Color.hxx"
#include "XCAFDoc_ColorTool.hxx"
#include "XCAFDoc_ColorType.hxx"
#include "XCAFDoc_LayerTool.hxx"
#include "XCAFDoc_DimTolTool.hxx"
#include "XCAFDoc_MaterialTool.hxx"
#include "XCAFDoc_DocumentTool.hxx"
#include "TDF_Label.hxx"
#include "TDF_LabelSequence.hxx"
#include "STEPCAFControl_Reader.hxx"
#include "STEPCAFControl_Writer.hxx"
#include "IGESCAFControl_Reader.hxx"
#include "IGESCAFControl_Writer.hxx"
#include "IGESControl_Reader.hxx"
#include "STEPControl_Reader.hxx"
#include "IGESControl_Writer.hxx"
#include "STEPControl_Writer.hxx"
#include <StepRepr_ValueRepresentationItem.hxx>
#include <StepRepr_IntegerRepresentationItem.hxx>
#include <StepRepr_CompoundRepresentationItem.hxx>
#include <StepBasic_MeasureValueMember.hxx>
#include "StlAPI_Writer.hxx"
#include "STEPControl_StepModelType.hxx"
#if OCC_VERSION_MAJOR>=7 && OCC_VERSION_MINOR>=4
#define OCC_HAVE_HISTORY
#endif
namespace netgen
{
#include "occmeshsurf.hpp"
// extern DLL_HEADER MeshingParameters mparam;
#define PROJECTION_TOLERANCE 1e-10
#define ENTITYISVISIBLE 1
#define ENTITYISHIGHLIGHTED 2
#define ENTITYISDRAWABLE 4
#define OCCGEOMETRYVISUALIZATIONNOCHANGE 0
#define OCCGEOMETRYVISUALIZATIONFULLCHANGE 1 // Compute transformation matrices and redraw
#define OCCGEOMETRYVISUALIZATIONHALFCHANGE 2 // Redraw
inline Point<3> occ2ng (const gp_Pnt & p)
{
return Point<3> (p.X(), p.Y(), p.Z());
}
inline Point<2> occ2ng (const gp_Pnt2d & p)
{
return Point<2> (p.X(), p.Y());
}
inline Vec<3> occ2ng (const gp_Vec & v)
{
return Vec<3> (v.X(), v.Y(), v.Z());
}
inline gp_Pnt ng2occ (const Point<3> & p)
{
return gp_Pnt(p(0), p(1), p(2));
}
class EntityVisualizationCode
{
int code;
public:
EntityVisualizationCode()
{ code = ENTITYISVISIBLE + !ENTITYISHIGHLIGHTED + ENTITYISDRAWABLE;}
int IsVisible ()
{ return code & ENTITYISVISIBLE;}
int IsHighlighted ()
{ return code & ENTITYISHIGHLIGHTED;}
int IsDrawable ()
{ return code & ENTITYISDRAWABLE;}
void Show ()
{ code |= ENTITYISVISIBLE;}
void Hide ()
{ code &= ~ENTITYISVISIBLE;}
void Highlight ()
{ code |= ENTITYISHIGHLIGHTED;}
void Lowlight ()
{ code &= ~ENTITYISHIGHLIGHTED;}
void SetDrawable ()
{ code |= ENTITYISDRAWABLE;}
void SetNotDrawable ()
{ code &= ~ENTITYISDRAWABLE;}
};
class Line
{
public:
Point<3> p0, p1;
double Dist (Line l);
double Length () { return (p1-p0).Length(); }
};
inline double Det3 (double a00, double a01, double a02,
double a10, double a11, double a12,
double a20, double a21, double a22)
{
return a00*a11*a22 + a01*a12*a20 + a10*a21*a02 - a20*a11*a02 - a10*a01*a22 - a21*a12*a00;
}
class DLL_HEADER OCCParameters
{
public:
/// Factor for meshing close edges, moved to meshingparameters
// double resthcloseedgefac = 2.;
/// Enable / Disable detection of close edges
// int resthcloseedgeenable = true;
/// Minimum edge length to be used for dividing edges to mesh points
double resthminedgelen = 0.001;
/// Enable / Disable use of the minimum edge length (by default use 1e-4)
int resthminedgelenenable = true;
/*!
Dump all the OpenCascade specific meshing parameters
to console
*/
void Print (ostream & ost) const;
};
class ShapeProperties
{
public:
optional<string> name;
optional<Vec<4>> col;
double maxh = 1e99;
double hpref = 0; // number of hp refinement levels (will be multiplied by factor later)
void Merge(const ShapeProperties & prop2)
{
if (prop2.name) name = prop2.name;
if (prop2.col) col = prop2.col;
maxh = min2(maxh, prop2.maxh);
}
void DoArchive(Archive& ar)
{
ar & name & col & maxh & hpref;
}
};
class OCCIdentification
{
public:
TopoDS_Shape other;
Transformation<3> trafo;
bool inverse;
string name;
};
class MyExplorer
{
class Iterator
{
TopExp_Explorer exp;
public:
Iterator (TopoDS_Shape ashape, TopAbs_ShapeEnum atoFind, TopAbs_ShapeEnum atoAvoid)
: exp(ashape, atoFind, atoAvoid) { }
auto operator*() { return exp.Current(); }
Iterator & operator++() { exp.Next(); return *this; }
bool operator!= (nullptr_t nu) { return exp.More(); }
};
public:
TopoDS_Shape shape;
TopAbs_ShapeEnum toFind;
TopAbs_ShapeEnum toAvoid;
MyExplorer (TopoDS_Shape ashape, TopAbs_ShapeEnum atoFind, TopAbs_ShapeEnum atoAvoid = TopAbs_SHAPE)
: shape(ashape), toFind(atoFind), toAvoid(atoAvoid) { ; }
Iterator begin() { return Iterator(shape, toFind, toAvoid); }
auto end() { return nullptr; }
};
inline auto Explore (TopoDS_Shape shape, TopAbs_ShapeEnum toFind, TopAbs_ShapeEnum toAvoid = TopAbs_SHAPE)
{
return MyExplorer (shape, toFind, toAvoid);
}
class IndexMapIterator
{
class Iterator
{
const TopTools_IndexedMapOfShape & indmap;
int i;
public:
Iterator (const TopTools_IndexedMapOfShape & aindmap, int ai)
: indmap(aindmap), i(ai) { ; }
auto operator*() { return tuple(i, indmap(i)); }
Iterator & operator++() { i++; return *this; }
bool operator!= (const Iterator & i2) { return i != i2.i; }
};
public:
const TopTools_IndexedMapOfShape & indmap;
IndexMapIterator (const TopTools_IndexedMapOfShape & aindmap) : indmap(aindmap) { }
Iterator begin() { return Iterator(indmap, 1); }
Iterator end() { return Iterator(indmap, indmap.Extent()+1); }
};
inline auto Enumerate (const TopTools_IndexedMapOfShape & indmap)
{
return IndexMapIterator(indmap);
}
class DLL_HEADER OCCGeometry : public NetgenGeometry
{
Point<3> center;
OCCParameters occparam;
public:
static std::map<Handle(TopoDS_TShape), ShapeProperties> global_shape_properties;
static std::map<Handle(TopoDS_TShape), std::vector<OCCIdentification>> identifications;
TopoDS_Shape shape;
TopTools_IndexedMapOfShape fmap, emap, vmap, somap, shmap, wmap;
NgArray<bool> fsingular, esingular, vsingular;
Box<3> boundingbox;
// should we use 1-based arrays (JS->MH) ?
Array<ShapeProperties*> fprops, eprops, sprops; // pointers to the gobal property map
mutable int changed;
mutable NgArray<int> facemeshstatus;
// Philippose - 15/01/2009
// Maximum mesh size for a given face
// (Used to explicitly define mesh size limits on individual faces)
NgArray<double> face_maxh;
// Philippose - 14/01/2010
// Boolean array to detect whether a face has been explicitly modified
// by the user or not
NgArray<bool> face_maxh_modified;
// Philippose - 15/01/2009
// Indicates which faces have been selected by the user in geometry mode
// (Currently handles only selection of one face at a time, but an array would
// help to extend this to multiple faces)
NgArray<bool> face_sel_status;
NgArray<EntityVisualizationCode> fvispar, evispar, vvispar;
double tolerance;
bool fixsmalledges;
bool fixspotstripfaces;
bool sewfaces;
bool makesolids;
bool splitpartitions;
int occdim = 3; // meshing is always done 3D, changed to 2D later of occdim=2
OCCGeometry()
{
somap.Clear();
shmap.Clear();
fmap.Clear();
wmap.Clear();
emap.Clear();
vmap.Clear();
}
OCCGeometry(const TopoDS_Shape& _shape, int aoccdim = 3, bool copy = false);
Mesh::GEOM_TYPE GetGeomType() const override
{ return Mesh::GEOM_OCC; }
void SetOCCParameters(const OCCParameters& par)
{ occparam = par; }
void Analyse(Mesh& mesh,
const MeshingParameters& mparam) const override;
void FindEdges(Mesh& mesh,
const MeshingParameters& mparam) const override;
void MeshSurface(Mesh& mesh,
const MeshingParameters& mparam) const override;
void FinalizeMesh(Mesh& mesh) const override;
void Save (string filename) const override;
void SaveToMeshFile (ostream & /* ost */) const override;
void DoArchive(Archive& ar) override;
PointGeomInfo ProjectPoint(int surfind, Point<3> & p) const override;
void ProjectPointEdge (int surfind, int surfind2, Point<3> & p,
EdgePointGeomInfo* gi = nullptr) const override;
bool ProjectPointGI (int surfind, Point<3> & p, PointGeomInfo & gi) const override;
Vec<3> GetNormal(int surfind, const Point<3> & p, const PointGeomInfo* gi) const override;
bool CalcPointGeomInfo(int surfind, PointGeomInfo& gi, const Point<3> & p3) const override;
void PointBetweenEdge(const Point<3> & p1, const Point<3> & p2, double secpoint,
int surfi1, int surfi2,
const EdgePointGeomInfo & ap1,
const EdgePointGeomInfo & ap2,
Point<3> & newp, EdgePointGeomInfo & newgi) const override;
void PointBetween(const Point<3> & p1, const Point<3> & p2, double secpoint,
int surfi,
const PointGeomInfo & gi1,
const PointGeomInfo & gi2,
Point<3> & newp, PointGeomInfo & newgi) const override;
void BuildFMap();
auto GetShape() const { return shape; }
Box<3> GetBoundingBox() const
{ return boundingbox; }
int NrSolids() const
{ return somap.Extent(); }
// Philippose - 17/01/2009
// Total number of faces in the geometry
int NrFaces() const
{ return fmap.Extent(); }
void SetCenter()
{ center = boundingbox.Center(); }
Point<3> Center() const
{ return center; }
OCCSurface GetSurface (int surfi)
{
cout << "OCCGeometry::GetSurface using PLANESPACE" << endl;
return OCCSurface (TopoDS::Face(fmap(surfi)), PLANESPACE);
}
void CalcBoundingBox ();
void BuildVisualizationMesh (double deflection);
void RecursiveTopologyTree (const TopoDS_Shape & sh,
stringstream & str,
TopAbs_ShapeEnum l,
bool free,
const char * lname);
void GetTopologyTree (stringstream & str);
void PrintNrShapes ();
void CheckIrregularEntities (stringstream & str);
void SewFaces();
void MakeSolid();
void HealGeometry();
void GlueGeometry();
// Philippose - 15/01/2009
// Sets the maximum mesh size for a given face
// (Note: Local mesh size limited by the global max mesh size)
void SetFaceMaxH(int facenr, double faceh, const MeshingParameters & mparam)
{
if((facenr> 0) && (facenr <= fmap.Extent()))
{
face_maxh[facenr-1] = min(mparam.maxh,faceh);
// Philippose - 14/01/2010
// If the face maxh is greater than or equal to the
// current global maximum, then identify the face as
// not explicitly controlled by the user any more
if(faceh >= mparam.maxh)
{
face_maxh_modified[facenr-1] = 0;
}
else
{
face_maxh_modified[facenr-1] = 1;
}
}
}
void SetFaceMaxH(size_t facenr, double faceh)
{
if(facenr >= fmap.Extent())
throw RangeException("OCCGeometry faces", facenr, 0, fmap.Extent());
face_maxh[facenr] = faceh;
face_maxh_modified[facenr] = true;
}
// Philippose - 15/01/2009
// Returns the local mesh size of a given face
double GetFaceMaxH(int facenr)
{
if((facenr> 0) && (facenr <= fmap.Extent()))
{
return face_maxh[facenr-1];
}
else
{
return 0.0;
}
}
// Philippose - 14/01/2010
// Returns the flag whether the given face
// has a mesh size controlled by the user or not
bool GetFaceMaxhModified(int facenr)
{
return face_maxh_modified[facenr-1];
}
// Philippose - 17/01/2009
// Returns the index of the currently selected face
int SelectedFace()
{
for(int i = 1; i <= fmap.Extent(); i++)
{
if(face_sel_status[i-1])
{
return i;
}
}
return 0;
}
// Philippose - 17/01/2009
// Sets the currently selected face
void SetSelectedFace(int facenr)
{
face_sel_status = 0;
if((facenr >= 1) && (facenr <= fmap.Extent()))
{
face_sel_status[facenr-1] = 1;
}
}
void LowLightAll()
{
for (int i = 1; i <= fmap.Extent(); i++)
fvispar[i-1].Lowlight();
for (int i = 1; i <= emap.Extent(); i++)
evispar[i-1].Lowlight();
for (int i = 1; i <= vmap.Extent(); i++)
vvispar[i-1].Lowlight();
}
void GetUnmeshedFaceInfo (stringstream & str);
void GetNotDrawableFaces (stringstream & str);
bool ErrorInSurfaceMeshing ();
// void WriteOCC_STL(char * filename);
private:
bool FastProject (int surfi, Point<3> & ap, double& u, double& v) const;
};
void PrintContents (OCCGeometry * geom);
DLL_HEADER OCCGeometry * LoadOCC_IGES (const char * filename);
DLL_HEADER OCCGeometry * LoadOCC_STEP (const char * filename);
DLL_HEADER OCCGeometry * LoadOCC_BREP (const char * filename);
// Philippose - 31.09.2009
// External access to the mesh generation functions within the OCC
// subsystem (Not sure if this is the best way to implement this....!!)
DLL_HEADER extern void OCCSetLocalMeshSize(const OCCGeometry & geom, Mesh & mesh, const MeshingParameters & mparam,
const OCCParameters& occparam);
DLL_HEADER extern void OCCMeshSurface (const OCCGeometry & geom, Mesh & mesh, const MeshingParameters & mparam);
DLL_HEADER extern void OCCOptimizeSurface (OCCGeometry & geom, Mesh & mesh, const MeshingParameters & mparam);
DLL_HEADER extern void OCCFindEdges (const OCCGeometry & geom, Mesh & mesh, const MeshingParameters & mparam);
namespace step_utils
{
inline Handle(TCollection_HAsciiString) MakeName (string s)
{
return new TCollection_HAsciiString(s.c_str());
};
inline Handle(StepRepr_RepresentationItem) MakeInt (int n, string name = "")
{
Handle(StepRepr_IntegerRepresentationItem) int_obj = new StepRepr_IntegerRepresentationItem;
int_obj->Init(MakeName(name), n);
return int_obj;
}
inline int ReadInt (Handle(StepRepr_RepresentationItem) item)
{
return Handle(StepRepr_IntegerRepresentationItem)::DownCast(item)->Value();
}
inline Handle(StepRepr_RepresentationItem) MakeReal (double val, string name = "")
{
Handle(StepBasic_MeasureValueMember) value_member = new StepBasic_MeasureValueMember;
value_member->SetReal(val);
Handle(StepRepr_ValueRepresentationItem) value_repr = new StepRepr_ValueRepresentationItem;
value_repr->Init(MakeName(name), value_member);
return value_repr;
}
inline double ReadReal (Handle(StepRepr_RepresentationItem) item)
{
return Handle(StepRepr_ValueRepresentationItem)::DownCast(item)
->ValueComponentMember()->Real();
}
inline Handle(StepRepr_RepresentationItem) MakeCompound( FlatArray<Handle(StepRepr_RepresentationItem)> items, string name = "" )
{
Handle(StepRepr_HArray1OfRepresentationItem) array_repr = new StepRepr_HArray1OfRepresentationItem(1,items.Size());
for(auto i : Range(items))
array_repr->SetValue(i+1, items[i]);
Handle(StepRepr_CompoundRepresentationItem) comp = new StepRepr_CompoundRepresentationItem;
comp->Init( MakeName(name), array_repr );
return comp;
}
void WriteIdentifications(const Handle(Interface_InterfaceModel) model, const TopoDS_Shape & shape, const Handle(Transfer_FinderProcess) finder);
void ReadIdentifications(Handle(StepRepr_RepresentationItem) item, Handle(Transfer_TransientProcess) transProc);
inline Quantity_ColorRGBA MakeColor(const Vec<4> & c)
{
return Quantity_ColorRGBA (c[0], c[1], c[2], c[3]);
}
inline Vec<4> ReadColor (const Quantity_ColorRGBA & c)
{
auto rgb = c.GetRGB();
return {rgb.Red(), rgb.Green(), rgb.Blue(), c.Alpha()};
}
void LoadProperties(const TopoDS_Shape & shape,
const STEPCAFControl_Reader & reader,
const Handle(TDocStd_Document) step_doc);
void WriteProperties(const Handle(Interface_InterfaceModel) model, const Handle(Transfer_FinderProcess) finder, const TopoDS_Shape & shape);
void WriteSTEP(const TopoDS_Shape & shape, string filename);
inline void WriteSTEP(const OCCGeometry & geo, string filename)
{
WriteSTEP(geo.GetShape(), filename);
}
// deep copy, also ensures consistent shape ordering (face numbers etc.)
TopoDS_Shape WriteAndRead(const TopoDS_Shape shape);
} // namespace step_utils
}
#endif
#endif