Loading files
3d097a032This file is pinned to the selected release. Download the original to open it in your design tool.
// Created on: 2008-04-11
// Created by: Peter KURNEV
// Copyright (c) 2008-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <BRep_Tool.hxx>
#include <BRepGProp.hxx>
#include <BRepMesh_DiscretAlgoFactory.hxx>
#include <BRepMesh_DiscretFactory.hxx>
#include <BRepMesh_DiscretRoot.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <DBRep.hxx>
#include <Draw.hxx>
#include <Draw_Interpretor.hxx>
#include <DrawTrSurf.hxx>
#include <gp_Vec.hxx>
#include <GProp_GProps.hxx>
#include <MeshTest.hxx>
#include <MeshTest_CheckTopology.hxx>
#include <NCollection_Map.hxx>
#include <Poly_Polygon2D.hxx>
#include <Poly_Polygon3D.hxx>
#include <Poly_PolygonOnTriangulation.hxx>
#include <Poly_Triangulation.hxx>
#include <Standard.hxx>
#include <gp_Pnt2d.hxx>
#include <NCollection_Array1.hxx>
#include <TCollection_AsciiString.hxx>
#include <Standard_Integer.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopTools_ShapeMapHasher.hxx>
#include <NCollection_IndexedMap.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Geom2d_BSplineCurve.hxx>
static int mpnames(Draw_Interpretor&, int, const char**);
static int mpsetdefaultname(Draw_Interpretor&, int, const char**);
static int mpgetdefaultname(Draw_Interpretor&, int, const char**);
static int mpincmesh(Draw_Interpretor&, int, const char**);
static int mpparallel(Draw_Interpretor&, int, const char**);
static int triarea(Draw_Interpretor&, int, const char**);
static int tricheck(Draw_Interpretor&, int, const char**);
//=================================================================================================
void MeshTest::PluginCommands(Draw_Interpretor& theCommands)
{
static bool done = false;
if (done)
{
return;
}
done = true;
//
const char* g = "Mesh Commands";
// Commands
theCommands.Add("mpnames", "mpnames : list available meshing algorithms", __FILE__, mpnames, g);
theCommands.Add("mpsetdefaultname",
"mpsetdefaultname name : set default meshing algorithm",
__FILE__,
mpsetdefaultname,
g);
theCommands.Add("mpgetdefaultname",
"mpgetdefaultname : get default meshing algorithm name",
__FILE__,
mpgetdefaultname,
g);
theCommands.Add("mpincmesh", "mpincmesh shape deflection [angle]", __FILE__, mpincmesh, g);
theCommands.Add("mpparallel",
"mpparallel [toTurnOn] : show / set multi-threading flag for incremental mesh",
__FILE__,
mpparallel,
g);
theCommands.Add("triarea",
"shape [eps] (computes triangles and surface area)",
__FILE__,
triarea,
g);
theCommands.Add("tricheck",
"shape [-small] (checks triangulation of shape);\n"
"\"-small\"-option allows finding triangles with small area",
__FILE__,
tricheck,
g);
}
//=================================================================================================
static int mpnames(Draw_Interpretor&, int n, const char**)
{
if (n != 1)
{
printf(" use mpnames\n");
return 0;
}
const NCollection_List<occ::handle<BRepMesh_DiscretAlgoFactory>>& aFactories =
BRepMesh_DiscretAlgoFactory::Factories();
if (aFactories.IsEmpty())
{
printf(" *no algorithms registered\n");
return 0;
}
printf(" *available algorithms:\n");
for (NCollection_List<occ::handle<BRepMesh_DiscretAlgoFactory>>::Iterator anIter(aFactories);
anIter.More();
anIter.Next())
{
printf(" %s\n", anIter.Value()->Name().ToCString());
}
return 0;
}
//=================================================================================================
static int mpsetdefaultname(Draw_Interpretor&, int n, const char** a)
{
if (n != 2)
{
printf(" use mpsetdefaultname name\n");
return 0;
}
TCollection_AsciiString aName = a[1];
if (BRepMesh_DiscretFactory::Get().SetDefaultName(aName))
{
printf(" *ready\n");
}
else
{
printf(" *algorithm '%s' not found\n", aName.ToCString());
}
return 0;
}
//=================================================================================================
static int mpgetdefaultname(Draw_Interpretor&, int n, const char**)
{
if (n != 1)
{
printf(" use mpgetdefaultname\n");
return 0;
}
const TCollection_AsciiString& aName = BRepMesh_DiscretFactory::Get().DefaultName();
printf(" *default name: %s\n", aName.ToCString());
return 0;
}
//=================================================================================================
static int mpincmesh(Draw_Interpretor&, int n, const char** a)
{
if (n < 3)
{
printf(" use mpincmesh shape deflection [angle]\n");
return 0;
}
TopoDS_Shape aS = DBRep::Get(a[1]);
if (aS.IsNull())
{
printf(" null shape is not allowed here\n");
return 0;
}
double aDeflection = Draw::Atof(a[2]);
double aAngle = 0.5;
if (n > 3)
{
aAngle = Draw::Atof(a[3]);
}
occ::handle<BRepMesh_DiscretRoot> aMeshAlgo =
BRepMesh_DiscretFactory::Get().Discret(aS, aDeflection, aAngle);
if (aMeshAlgo.IsNull())
{
printf(" *Cannot create the meshing algorithm\n");
return 0;
}
aMeshAlgo->Perform();
if (!aMeshAlgo->IsDone())
{
printf(" *Meshing not done\n");
}
return 0;
}
// #######################################################################
static int triarea(Draw_Interpretor& di, int n, const char** a)
{
if (n < 2)
{
return 1;
}
TopoDS_Shape shape = DBRep::Get(a[1]);
if (shape.IsNull())
{
return 1;
}
double anEps = -1.;
if (n > 2)
{
anEps = Draw::Atof(a[2]);
}
NCollection_IndexedMap<TopoDS_Shape, TopTools_ShapeMapHasher> aMapF;
TopExp::MapShapes(shape, TopAbs_FACE, aMapF);
// detect if a shape has triangulation
bool hasPoly = false;
int i;
for (i = 1; i <= aMapF.Extent(); i++)
{
const TopoDS_Face& aFace = TopoDS::Face(aMapF(i));
TopLoc_Location aLoc;
occ::handle<Poly_Triangulation> aPoly = BRep_Tool::Triangulation(aFace, aLoc);
if (!aPoly.IsNull())
{
hasPoly = true;
break;
}
}
// compute area by triangles
double aTriArea = 0;
if (hasPoly)
{
for (i = 1; i <= aMapF.Extent(); i++)
{
const TopoDS_Face& aFace = TopoDS::Face(aMapF(i));
TopLoc_Location aLoc;
occ::handle<Poly_Triangulation> aPoly = BRep_Tool::Triangulation(aFace, aLoc);
if (aPoly.IsNull())
{
std::cout << "face " << i << " has no triangulation" << '\n';
continue;
}
for (int j = 1; j <= aPoly->NbTriangles(); j++)
{
const Poly_Triangle tri = aPoly->Triangle(j);
int n1, n2, n3;
tri.Get(n1, n2, n3);
const gp_Pnt p1 = aPoly->Node(n1);
const gp_Pnt p2 = aPoly->Node(n2);
const gp_Pnt p3 = aPoly->Node(n3);
gp_Vec v1(p1, p2);
gp_Vec v2(p1, p3);
double ar = v1.CrossMagnitude(v2);
aTriArea += ar;
}
}
aTriArea /= 2;
}
// compute area by geometry
GProp_GProps props;
if (anEps <= 0.)
{
BRepGProp::SurfaceProperties(shape, props);
}
else
{
BRepGProp::SurfaceProperties(shape, props, anEps);
}
double aGeomArea = props.Mass();
di << aTriArea << " " << aGeomArea << "\n";
return 0;
}
// #######################################################################
bool IsEqual(const BRepMesh_Edge& theFirst, const BRepMesh_Edge& theSecond)
{
return theFirst.IsEqual(theSecond);
}
static int tricheck(Draw_Interpretor& di, int n, const char** a)
{
if (n < 2)
{
return 1;
}
TopoDS_Shape shape = DBRep::Get(a[1]);
if (shape.IsNull())
{
return 1;
}
const bool isToFindSmallTriangles = (n >= 3) ? (strcmp(a[2], "-small") == 0) : false;
NCollection_IndexedMap<TopoDS_Shape, TopTools_ShapeMapHasher> aMapF;
TopExp::MapShapes(shape, TopAbs_FACE, aMapF);
const char* const name = ".";
// execute check
MeshTest_CheckTopology aCheck(shape);
aCheck.Perform(di);
// dump info on free links inside the triangulation
int nbFree = 0;
int nbFac = aCheck.NbFacesWithFL(), i, k;
if (nbFac > 0)
{
for (k = 1; k <= nbFac; k++)
{
int nbEdge = aCheck.NbFreeLinks(k);
int iF = aCheck.GetFaceNumWithFL(k);
nbFree += nbEdge;
di << "free links of face " << iF << "\n";
const TopoDS_Shape& aShape = aMapF.FindKey(iF);
const TopoDS_Face& aFace = TopoDS::Face(aShape);
TopLoc_Location aLoc;
occ::handle<Poly_Triangulation> aT = BRep_Tool::Triangulation(aFace, aLoc);
const gp_Trsf& trsf = aLoc.Transformation();
NCollection_Array1<gp_Pnt> pnts(1, 2);
NCollection_Array1<gp_Pnt2d> pnts2d(1, 2);
for (i = 1; i <= nbEdge; i++)
{
int n1, n2;
aCheck.GetFreeLink(k, i, n1, n2);
di << "{" << n1 << " " << n2 << "} ";
pnts(1) = aT->Node(n1).Transformed(trsf);
pnts(2) = aT->Node(n2).Transformed(trsf);
occ::handle<Poly_Polygon3D> poly = new Poly_Polygon3D(pnts);
DrawTrSurf::Set(name, poly);
DrawTrSurf::Set(name, pnts(1));
DrawTrSurf::Set(name, pnts(2));
if (aT->HasUVNodes())
{
pnts2d(1) = aT->UVNode(n1);
pnts2d(2) = aT->UVNode(n2);
occ::handle<Poly_Polygon2D> poly2d = new Poly_Polygon2D(pnts2d);
DrawTrSurf::Set(name, poly2d);
DrawTrSurf::Set(name, pnts2d(1));
DrawTrSurf::Set(name, pnts2d(2));
}
}
di << "\n";
}
}
// dump info on cross face errors
int nbErr = aCheck.NbCrossFaceErrors();
if (nbErr > 0)
{
di << "cross face errors: {face1, node1, face2, node2, distance}\n";
for (i = 1; i <= nbErr; i++)
{
int iF1, n1, iF2, n2;
double aVal;
aCheck.GetCrossFaceError(i, iF1, n1, iF2, n2, aVal);
di << "{" << iF1 << " " << n1 << " " << iF2 << " " << n2 << " " << aVal << "} ";
}
di << "\n";
}
// dump info on edges
int nbAsync = aCheck.NbAsyncEdges();
if (nbAsync > 0)
{
di << "async edges:\n";
for (i = 1; i <= nbAsync; i++)
{
int ie = aCheck.GetAsyncEdgeNum(i);
di << ie << " ";
}
di << "\n";
}
// dump info on free nodes
int nbFreeNodes = aCheck.NbFreeNodes();
if (nbFreeNodes > 0)
{
di << "free nodes (in pairs: face / node): \n";
for (i = 1; i <= nbFreeNodes; i++)
{
int iface, inode;
aCheck.GetFreeNodeNum(i, iface, inode);
const TopoDS_Face& aFace = TopoDS::Face(aMapF.FindKey(iface));
TopLoc_Location aLoc;
occ::handle<Poly_Triangulation> aT = BRep_Tool::Triangulation(aFace, aLoc);
const gp_Trsf& trsf = aLoc.Transformation();
DrawTrSurf::Set(name, aT->Node(inode).Transformed(trsf));
if (aT->HasUVNodes())
{
DrawTrSurf::Set(name, aT->UVNode(inode));
}
di << "{" << iface << " " << inode << "} ";
}
di << "\n";
}
const int aNbSmallTriangles = isToFindSmallTriangles ? aCheck.NbSmallTriangles() : 0;
if (aNbSmallTriangles > 0)
{
di << "triangles with null area (in pairs: face / triangle): \n";
for (i = 1; i <= aNbSmallTriangles; i++)
{
int aFaceId = 0, aTriID = 0;
aCheck.GetSmallTriangle(i, aFaceId, aTriID);
const TopoDS_Face& aFace = TopoDS::Face(aMapF.FindKey(aFaceId));
TopLoc_Location aLoc;
const gp_Trsf& aTrsf = aLoc.Transformation();
const occ::handle<Poly_Triangulation> aT = BRep_Tool::Triangulation(aFace, aLoc);
const Poly_Triangle& aTri = aT->Triangle(aTriID);
int aN1, aN2, aN3;
aTri.Get(aN1, aN2, aN3);
NCollection_Array1<gp_Pnt> aPoles(1, 4);
aPoles(1) = aPoles(4) = aT->Node(aN1).Transformed(aTrsf);
aPoles(2) = aT->Node(aN2).Transformed(aTrsf);
aPoles(3) = aT->Node(aN3).Transformed(aTrsf);
NCollection_Array1<int> aMults(1, 4);
aMults(1) = aMults(4) = 2;
aMults(2) = aMults(3) = 1;
NCollection_Array1<double> aKnots(1, 4);
aKnots(1) = 1.0;
aKnots(2) = 2.0;
aKnots(3) = 3.0;
aKnots(4) = 4.0;
occ::handle<Geom_BSplineCurve> aBS = new Geom_BSplineCurve(aPoles, aKnots, aMults, 1);
DrawTrSurf::Set(name, aBS);
if (aT->HasUVNodes())
{
NCollection_Array1<gp_Pnt2d> aPoles2d(1, 4);
aPoles2d(1) = aPoles2d(4) = aT->UVNode(aN1);
aPoles2d(2) = aT->UVNode(aN2);
aPoles2d(3) = aT->UVNode(aN3);
occ::handle<Geom2d_BSplineCurve> aBS2d =
new Geom2d_BSplineCurve(aPoles2d, aKnots, aMults, 1);
DrawTrSurf::Set(name, aBS2d);
}
di << "{" << aFaceId << " " << aTriID << "} ";
}
di << "\n";
}
// output errors summary to DRAW
if (nbFree > 0 || nbErr > 0 || nbAsync > 0 || nbFreeNodes > 0 || (aNbSmallTriangles > 0))
{
di << "Free_links " << nbFree << " Cross_face_errors " << nbErr << " Async_edges " << nbAsync
<< " Free_nodes " << nbFreeNodes << " Small triangles " << aNbSmallTriangles << "\n";
}
int aFaceId = 1;
TopExp_Explorer aFaceExp(shape, TopAbs_FACE);
for (; aFaceExp.More(); aFaceExp.Next(), ++aFaceId)
{
const TopoDS_Shape& aShape = aFaceExp.Current();
const TopoDS_Face& aFace = TopoDS::Face(aShape);
TopLoc_Location aLoc;
occ::handle<Poly_Triangulation> aT = BRep_Tool::Triangulation(aFace, aLoc);
// Iterate boundary edges
NCollection_Map<BRepMesh_Edge> aBoundaryEdgeMap;
TopExp_Explorer anExp(aShape, TopAbs_EDGE);
for (; anExp.More(); anExp.Next())
{
TopLoc_Location anEdgeLoc;
const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current());
occ::handle<Poly_PolygonOnTriangulation> aPoly =
BRep_Tool::PolygonOnTriangulation(anEdge, aT, aLoc);
if (aPoly.IsNull())
{
continue;
}
const NCollection_Array1<int>& anIndices = aPoly->Nodes();
int aLower = anIndices.Lower();
int anUpper = anIndices.Upper();
int aPrevNode = -1;
for (int j = aLower; j <= anUpper; ++j)
{
int aNodeIdx = anIndices.Value(j);
if (j != aLower)
{
BRepMesh_Edge aLink(aPrevNode, aNodeIdx, BRepMesh_Frontier);
aBoundaryEdgeMap.Add(aLink);
}
aPrevNode = aNodeIdx;
}
}
if (aBoundaryEdgeMap.Size() == 0)
{
break;
}
NCollection_Map<BRepMesh_Edge> aFreeEdgeMap;
const int aTriNum = aT->NbTriangles();
for (int aTriIndx = 1; aTriIndx <= aTriNum; aTriIndx++)
{
const Poly_Triangle aTri = aT->Triangle(aTriIndx);
int aTriNodes[3] = {aTri.Value(1), aTri.Value(2), aTri.Value(3)};
for (int j = 1; j <= 3; ++j)
{
int aLastId = aTriNodes[j % 3];
int aFirstId = aTriNodes[j - 1];
BRepMesh_Edge aLink(aFirstId, aLastId, BRepMesh_Free);
if (!aBoundaryEdgeMap.Contains(aLink))
{
if (!aFreeEdgeMap.Add(aLink))
{
aFreeEdgeMap.Remove(aLink);
}
}
}
}
if (aFreeEdgeMap.Size() != 0)
{
di << "Not connected mesh inside face " << aFaceId << "\n";
const gp_Trsf& trsf = aLoc.Transformation();
NCollection_Array1<gp_Pnt> pnts(1, 2);
NCollection_Array1<gp_Pnt2d> pnts2d(1, 2);
NCollection_Map<BRepMesh_Edge>::Iterator aMapIt(aFreeEdgeMap);
for (; aMapIt.More(); aMapIt.Next())
{
const BRepMesh_Edge& aLink = aMapIt.Key();
di << "{" << aLink.FirstNode() << " " << aLink.LastNode() << "} ";
pnts(1) = aT->Node(aLink.FirstNode()).Transformed(trsf);
pnts(2) = aT->Node(aLink.LastNode()).Transformed(trsf);
occ::handle<Poly_Polygon3D> poly = new Poly_Polygon3D(pnts);
DrawTrSurf::Set(name, poly);
DrawTrSurf::Set(name, pnts(1));
DrawTrSurf::Set(name, pnts(2));
if (aT->HasUVNodes())
{
pnts2d(1) = aT->UVNode(aLink.FirstNode());
pnts2d(2) = aT->UVNode(aLink.LastNode());
occ::handle<Poly_Polygon2D> poly2d = new Poly_Polygon2D(pnts2d);
DrawTrSurf::Set(name, poly2d);
DrawTrSurf::Set(name, pnts2d(1));
DrawTrSurf::Set(name, pnts2d(2));
}
}
di << "\n";
}
}
return 0;
}
//=================================================================================================
static int mpparallel(Draw_Interpretor& /*di*/, int argc, const char** argv)
{
if (argc == 2)
{
bool isParallelOn = Draw::Atoi(argv[1]) == 1;
BRepMesh_IncrementalMesh::SetParallelDefault(isParallelOn);
}
std::cout << "Incremental Mesh, multi-threading "
<< (BRepMesh_IncrementalMesh::IsParallelDefault() ? "ON\n" : "OFF\n");
return 0;
}