23
#include "PreCompiled.h"
26
# include <BRep_Tool.hxx>
27
# include <BRepAdaptor_Curve.hxx>
28
# include <BRepAdaptor_Surface.hxx>
29
# include <BRepBuilderAPI_MakeEdge.hxx>
30
# include <BRepBuilderAPI_MakeFace.hxx>
31
# include <BRepLProp_SLProps.hxx>
32
# include <BRepMesh_IncrementalMesh.hxx>
34
# include <Geom_BSplineSurface.hxx>
35
# include <Geom_Line.hxx>
36
# include <Geom_Plane.hxx>
37
# include <Geom_Point.hxx>
38
# include <GeomAPI_IntSS.hxx>
39
# include <GeomAPI_ProjectPointOnSurf.hxx>
40
# include <GeomAdaptor_Curve.hxx>
41
# include <GeomLib.hxx>
42
# include <GeomLProp_SLProps.hxx>
43
# include <GeomPlate_BuildPlateSurface.hxx>
44
# include <GeomPlate_CurveConstraint.hxx>
45
# include <GeomPlate_MakeApprox.hxx>
46
# include <GeomPlate_PlateG0Criterion.hxx>
47
# include <GeomPlate_PointConstraint.hxx>
50
# include <gp_Quaternion.hxx>
51
# include <Poly_Connect.hxx>
52
# include <Poly_Triangulation.hxx>
53
# include <Precision.hxx>
54
# include <Standard_Mutex.hxx>
55
# include <Standard_TypeMismatch.hxx>
56
# include <Standard_Version.hxx>
57
# include <TColStd_ListIteratorOfListOfTransient.hxx>
58
# include <TColStd_ListOfTransient.hxx>
59
# include <TColgp_SequenceOfXY.hxx>
60
# include <TColgp_SequenceOfXYZ.hxx>
62
# if OCC_VERSION_HEX < 0x070600
63
# include <Adaptor3d_HCurveOnSurface.hxx>
64
# include <GeomAdaptor_HCurve.hxx>
68
#include <Base/Exception.h>
69
#include <Base/Vector3D.h>
74
void Part::closestPointsOnLines(const gp_Lin& lin1, const gp_Lin& lin2, gp_Pnt& p1, gp_Pnt& p2)
77
gp_Vec v1(lin1.Direction());
78
gp_Vec v2(lin2.Direction());
79
gp_Vec v3(lin2.Location(), lin1.Location());
90
if (D < Precision::Angular()){
93
t = (b>c ? d/b : e/c);
100
p1 = lin1.Location().XYZ() + s * v1.XYZ();
101
p2 = lin2.Location().XYZ() + t * v2.XYZ();
104
bool Part::intersect(const gp_Pln& pln1, const gp_Pln& pln2, gp_Lin& lin)
107
Handle (Geom_Plane) gp1 = new Geom_Plane(pln1);
108
Handle (Geom_Plane) gp2 = new Geom_Plane(pln2);
110
GeomAPI_IntSS intSS(gp1, gp2, Precision::Confusion());
111
if (intSS.IsDone()) {
112
int numSol = intSS.NbLines();
114
Handle(Geom_Curve) curve = intSS.Line(1);
115
lin = Handle(Geom_Line)::DownCast(curve)->Lin();
133
Part::Tools::makeSurface(const TColStd_ListOfTransient &theBoundaries,
134
const Standard_Real theTol,
135
const Standard_Integer theNbPnts,
136
const Standard_Integer theNbIter,
137
const Standard_Integer theMaxDeg)
141
const Standard_Integer aNbIter = theNbIter;
142
const Standard_Integer aNbPnts = theNbPnts;
143
const Standard_Integer aDeg = 3;
144
const Standard_Integer aMaxDeg = theMaxDeg;
145
const Standard_Integer aMaxSeg = 10000;
146
const Standard_Real aTol3d = 1.e-04;
147
const Standard_Real aTol2d = 1.e-05;
148
const Standard_Real anAngTol = 1.e-02;
149
const Standard_Real aCurvTol = 1.e-01;
151
Handle(Geom_Surface) aRes;
152
GeomPlate_BuildPlateSurface aPlateBuilder (aDeg, aNbPnts, aNbIter, aTol2d, aTol3d, anAngTol, aCurvTol);
154
TColStd_ListIteratorOfListOfTransient anIt (theBoundaries);
157
for (; anIt.More(); anIt.Next(), i++) {
158
const Handle(Standard_Transient)& aCur = anIt.Value();
161
Standard_ConstructionError::Raise ("Tools::makeSurface()");
163
#if OCC_VERSION_HEX >= 0x070600
164
else if (aCur->IsKind (STANDARD_TYPE (Adaptor3d_CurveOnSurface))) {
166
Handle(Adaptor3d_CurveOnSurface) aHCOS (Handle(Adaptor3d_CurveOnSurface)::DownCast (aCur));
167
Handle (GeomPlate_CurveConstraint) aConst = new GeomPlate_CurveConstraint (aHCOS, 1 ,aNbPnts, aTol3d, anAngTol, aCurvTol);
168
aPlateBuilder.Add (aConst);
170
else if (aCur->IsKind (STANDARD_TYPE (GeomAdaptor_Curve))) {
172
Handle(GeomAdaptor_Curve) aHC (Handle(GeomAdaptor_Curve)::DownCast (aCur));
173
Handle (GeomPlate_CurveConstraint) aConst = new GeomPlate_CurveConstraint (aHC, 0 , aNbPnts, aTol3d);
174
aPlateBuilder.Add (aConst);
177
else if (aCur->IsKind (STANDARD_TYPE (Adaptor3d_HCurveOnSurface))) {
179
Handle(Adaptor3d_HCurveOnSurface) aHCOS (Handle(Adaptor3d_HCurveOnSurface)::DownCast (aCur));
180
Handle (GeomPlate_CurveConstraint) aConst = new GeomPlate_CurveConstraint (aHCOS, 1 ,aNbPnts, aTol3d, anAngTol, aCurvTol);
181
aPlateBuilder.Add (aConst);
183
else if (aCur->IsKind (STANDARD_TYPE (GeomAdaptor_HCurve))) {
185
Handle(GeomAdaptor_HCurve) aHC (Handle(GeomAdaptor_HCurve)::DownCast (aCur));
186
Handle (GeomPlate_CurveConstraint) aConst = new GeomPlate_CurveConstraint (aHC, 0 , aNbPnts, aTol3d);
187
aPlateBuilder.Add (aConst);
190
else if (aCur->IsKind (STANDARD_TYPE (Geom_Point))) {
192
Handle(Geom_Point) aGP (Handle(Geom_Point)::DownCast (aCur));
193
Handle(GeomPlate_PointConstraint) aConst = new GeomPlate_PointConstraint(aGP->Pnt(),0);
194
aPlateBuilder.Add(aConst);
197
Standard_TypeMismatch::Raise ("Tools::makeSurface()");
202
Standard_ConstructionError::Raise ("Tools::makeSurface()");
206
aPlateBuilder.Perform();
208
if (!aPlateBuilder.IsDone()) {
212
const Handle(GeomPlate_Surface)& aPlate = aPlateBuilder.Surface();
214
Standard_Real aDMax = aPlateBuilder.G0Error();
215
TColgp_SequenceOfXY aS2d;
216
TColgp_SequenceOfXYZ aS3d;
217
aPlateBuilder.Disc2dContour (4, aS2d);
218
aPlateBuilder.Disc3dContour (4, 0, aS3d);
219
Standard_Real aMax = Max (aTol3d, 10. * aDMax);
220
GeomPlate_PlateG0Criterion aCriterion (aS2d, aS3d, aMax);
224
GeomPlate_MakeApprox aMakeApprox (aPlate, aCriterion, aTol3d, aMaxSeg, aMaxDeg);
225
aRes = aMakeApprox.Surface();
231
bool Part::Tools::getTriangulation(const TopoDS_Face& face, std::vector<gp_Pnt>& points, std::vector<Poly_Triangle>& facets)
234
Handle(Poly_Triangulation) hTria = BRep_Tool::Triangulation(face, loc);
240
bool identity = true;
241
if (!loc.IsIdentity()) {
243
transf = loc.Transformation();
247
TopAbs_Orientation orient = face.Orientation();
249
Standard_Integer nbNodes = hTria->NbNodes();
250
Standard_Integer nbTriangles = hTria->NbTriangles();
251
#if OCC_VERSION_HEX < 0x070600
252
const TColgp_Array1OfPnt& nodes = hTria->Nodes();
253
const Poly_Array1OfTriangle& triangles = hTria->Triangles();
256
points.reserve(nbNodes);
257
facets.reserve(nbTriangles);
261
for (int i = 1; i <= nbNodes; i++) {
262
#if OCC_VERSION_HEX < 0x070600
265
gp_Pnt p = hTria->Node(i);
276
for (int i = 1; i <= nbTriangles; i++) {
278
Standard_Integer n1,n2,n3;
279
#if OCC_VERSION_HEX < 0x070600
280
triangles(i).Get(n1, n2, n3);
282
hTria->Triangle(i).Get(n1, n2, n3);
287
if (orient != TopAbs_FORWARD) {
291
facets.emplace_back(n1, n2, n3);
297
bool Part::Tools::getPolygonOnTriangulation(const TopoDS_Edge& edge, const TopoDS_Face& face, std::vector<gp_Pnt>& points)
300
Handle(Poly_Triangulation) hTria = BRep_Tool::Triangulation(face, loc);
305
Handle(Poly_PolygonOnTriangulation) hPoly = BRep_Tool::PolygonOnTriangulation(edge, hTria, loc);
311
bool identity = true;
312
if (!loc.IsIdentity()) {
314
transf = loc.Transformation();
318
Standard_Integer nbNodes = hPoly->NbNodes();
319
points.reserve(nbNodes);
320
const TColStd_Array1OfInteger& indices = hPoly->Nodes();
321
#if OCC_VERSION_HEX < 0x070600
322
const TColgp_Array1OfPnt& Nodes = hTria->Nodes();
326
for (Standard_Integer i = indices.Lower(); i <= indices.Upper(); i++) {
327
#if OCC_VERSION_HEX < 0x070600
328
gp_Pnt p = Nodes(indices(i));
330
gp_Pnt p = hTria->Node(indices(i));
342
bool Part::Tools::getPolygon3D(const TopoDS_Edge& edge, std::vector<gp_Pnt>& points)
345
Handle(Poly_Polygon3D) hPoly = BRep_Tool::Polygon3D(edge, loc);
351
bool identity = true;
352
if (!loc.IsIdentity()) {
354
transf = loc.Transformation();
358
Standard_Integer nbNodes = hPoly->NbNodes();
359
points.reserve(nbNodes);
360
const TColgp_Array1OfPnt& nodes = hPoly->Nodes();
362
for (int i = 1; i <= nbNodes; i++) {
376
void Part::Tools::getPointNormals(const std::vector<gp_Pnt>& points, const std::vector<Poly_Triangle>& facets, std::vector<gp_Vec>& vertexnormals)
378
vertexnormals.resize(points.size());
380
for (const auto& it : facets) {
382
Standard_Integer n1,n2,n3;
386
gp_Vec v1(points[n1].XYZ());
387
gp_Vec v2(points[n2].XYZ());
388
gp_Vec v3(points[n3].XYZ());
389
gp_Vec n = (v2 - v1) ^ (v3 - v1);
392
vertexnormals[n1] += n;
393
vertexnormals[n2] += n;
394
vertexnormals[n3] += n;
397
for (auto& it : vertexnormals)
401
void Part::Tools::getPointNormals(const std::vector<gp_Pnt>& points, const TopoDS_Face& face, std::vector<gp_Vec>& vertexnormals)
403
if (points.size() != vertexnormals.size())
406
Handle(Geom_Surface) hSurface = BRep_Tool::Surface(face);
407
if (hSurface.IsNull())
411
for (std::size_t i = 0; i < points.size(); i++) {
413
GeomAPI_ProjectPointOnSurf ProPntSrf(points[i], hSurface);
415
ProPntSrf.Parameters(1, u, v);
417
GeomLProp_SLProps propOfFace(hSurface, u, v, 2, gp::Resolution());
419
gp_Dir normal = propOfFace.Normal();
420
gp_Vec temp = normal;
421
if (temp * vertexnormals[i] < 0.0)
423
vertexnormals[i] = temp;
429
vertexnormals[i].Normalize();
433
void Part::Tools::getPointNormals(const TopoDS_Face& theFace, Handle(Poly_Triangulation) aPolyTri, TColgp_Array1OfDir& theNormals)
435
#if OCC_VERSION_HEX < 0x070600
436
const TColgp_Array1OfPnt& aNodes = aPolyTri->Nodes();
438
if(aPolyTri->HasNormals())
441
const TShort_Array1OfShortReal& aNormals = aPolyTri->Normals();
442
const Standard_ShortReal* aNormArr = &(aNormals.Value(aNormals.Lower()));
444
for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
446
const Standard_Integer anId = 3 * (aNodeIter - aNodes.Lower());
447
const gp_Dir aNorm(aNormArr[anId + 0],
450
theNormals(aNodeIter) = aNorm;
453
if(theFace.Orientation() == TopAbs_REVERSED)
455
for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
457
theNormals.ChangeValue(aNodeIter).Reverse();
463
Poly_Connect thePolyConnect(aPolyTri);
464
const TopoDS_Face aZeroFace = TopoDS::Face(theFace.Located(TopLoc_Location()));
465
Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aZeroFace);
466
const Standard_Real aTol = Precision::Confusion();
467
Handle(TShort_HArray1OfShortReal) aNormals = new TShort_HArray1OfShortReal(1, aPolyTri->NbNodes() * 3);
468
const Poly_Array1OfTriangle& aTriangles = aPolyTri->Triangles();
469
const TColgp_Array1OfPnt2d* aNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull()
470
? &aPolyTri->UVNodes()
472
Standard_Integer aTri[3];
474
for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
477
if (!aNodesUV || GeomLib::NormEstim(aSurf, aNodesUV->Value(aNodeIter), aTol, theNormals(aNodeIter)) > 1)
480
gp_XYZ eqPlan(0.0, 0.0, 0.0);
482
for(thePolyConnect.Initialize(aNodeIter); thePolyConnect.More(); thePolyConnect.Next())
484
aTriangles(thePolyConnect.Value()).Get(aTri[0], aTri[1], aTri[2]);
485
const gp_XYZ v1(aNodes(aTri[1]).Coord() - aNodes(aTri[0]).Coord());
486
const gp_XYZ v2(aNodes(aTri[2]).Coord() - aNodes(aTri[1]).Coord());
487
const gp_XYZ vv = v1 ^ v2;
488
const Standard_Real aMod = vv.Modulus();
496
const Standard_Real aModMax = eqPlan.Modulus();
497
theNormals(aNodeIter) = (aModMax > aTol) ? gp_Dir(eqPlan) : gp::DZ();
500
const Standard_Integer anId = (aNodeIter - aNodes.Lower()) * 3;
501
aNormals->SetValue(anId + 1, (Standard_ShortReal)theNormals(aNodeIter).X());
502
aNormals->SetValue(anId + 2, (Standard_ShortReal)theNormals(aNodeIter).Y());
503
aNormals->SetValue(anId + 3, (Standard_ShortReal)theNormals(aNodeIter).Z());
506
aPolyTri->SetNormals(aNormals);
508
if(theFace.Orientation() == TopAbs_REVERSED)
510
for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
512
theNormals.ChangeValue(aNodeIter).Reverse();
517
Standard_Integer numNodes = aPolyTri->NbNodes();
519
if(aPolyTri->HasNormals())
521
for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter)
523
theNormals(aNodeIter) = aPolyTri->Normal(aNodeIter);
526
if(theFace.Orientation() == TopAbs_REVERSED)
528
for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter)
530
theNormals.ChangeValue(aNodeIter).Reverse();
536
Poly_Connect thePolyConnect(aPolyTri);
537
const TopoDS_Face aZeroFace = TopoDS::Face(theFace.Located(TopLoc_Location()));
538
Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aZeroFace);
539
const Standard_Real aTol = Precision::Confusion();
540
Standard_Boolean hasNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull();
541
Standard_Integer aTri[3];
543
aPolyTri->AddNormals();
544
for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter)
547
if (!hasNodesUV || GeomLib::NormEstim(aSurf, aPolyTri->UVNode(aNodeIter), aTol, theNormals(aNodeIter)) > 1)
550
gp_XYZ eqPlan(0.0, 0.0, 0.0);
552
for(thePolyConnect.Initialize(aNodeIter); thePolyConnect.More(); thePolyConnect.Next())
554
aPolyTri->Triangle(thePolyConnect.Value()).Get(aTri[0], aTri[1], aTri[2]);
555
const gp_XYZ v1(aPolyTri->Node(aTri[1]).Coord() - aPolyTri->Node(aTri[0]).Coord());
556
const gp_XYZ v2(aPolyTri->Node(aTri[2]).Coord() - aPolyTri->Node(aTri[1]).Coord());
557
const gp_XYZ vv = v1 ^ v2;
558
const Standard_Real aMod = vv.Modulus();
566
const Standard_Real aModMax = eqPlan.Modulus();
567
theNormals(aNodeIter) = (aModMax > aTol) ? gp_Dir(eqPlan) : gp::DZ();
570
aPolyTri->SetNormal(aNodeIter, theNormals(aNodeIter));
573
if(theFace.Orientation() == TopAbs_REVERSED)
575
for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter)
577
theNormals.ChangeValue(aNodeIter).Reverse();
584
void Part::Tools::getPointNormals(const TopoDS_Face& face, Handle(Poly_Triangulation) aPoly, std::vector<gp_Vec>& normals)
586
TColgp_Array1OfDir dirs (1, aPoly->NbNodes());
587
getPointNormals(face, aPoly, dirs);
588
normals.reserve(aPoly->NbNodes());
590
for (int i = dirs.Lower(); i <= dirs.Upper(); ++i) {
591
normals.emplace_back(dirs(i).XYZ());
595
void Part::Tools::applyTransformationOnNormals(const TopLoc_Location& loc, std::vector<gp_Vec>& normals)
597
if (!loc.IsIdentity()) {
598
gp_Trsf myTransf = loc.Transformation();
600
for (auto& it : normals) {
601
it.Transform(myTransf);
606
Handle (Poly_Triangulation) Part::Tools::triangulationOfFace(const TopoDS_Face& face)
609
Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(face, loc);
614
double u1{}, u2{}, v1{}, v2{};
616
BRepAdaptor_Surface adapt(face);
617
u1 = adapt.FirstUParameter();
618
u2 = adapt.LastUParameter();
619
v1 = adapt.FirstVParameter();
620
v2 = adapt.LastVParameter();
622
catch (const Standard_Failure&) {
626
auto selectRange = [](double& p1, double& p2) {
627
if (Precision::IsInfinite(p1) && Precision::IsInfinite(p2)) {
631
else if (Precision::IsInfinite(p1)) {
634
else if (Precision::IsInfinite(p2)) {
643
Handle(Geom_Surface) surface = BRep_Tool::Surface(face);
644
if ( surface.IsNull() ) {
645
FC_THROWM(Base::CADKernelError, "Cannot create surface from face");
647
BRepBuilderAPI_MakeFace mkBuilder(surface, u1, u2, v1, v2, Precision::Confusion() );
648
TopoDS_Shape shape = mkBuilder.Shape();
651
BRepMesh_IncrementalMesh(shape, 0.005, false, 0.1, true);
652
return BRep_Tool::Triangulation(TopoDS::Face(shape), loc);
655
Handle(Poly_Polygon3D) Part::Tools::polygonOfEdge(const TopoDS_Edge& edge, TopLoc_Location& loc)
657
BRepAdaptor_Curve adapt(edge);
658
double u = adapt.FirstParameter();
659
double v = adapt.LastParameter();
660
Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(edge, loc);
661
if (!aPoly.IsNull() && !Precision::IsInfinite(u) && !Precision::IsInfinite(v))
665
u = std::max(-50.0, u);
666
v = std::min( 50.0, v);
669
Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, uv, uv);
671
BRepBuilderAPI_MakeEdge mkBuilder(curve, u, v);
672
TopoDS_Shape shape = mkBuilder.Shape();
674
TopLoc_Location inv = loc.Inverted();
677
BRepMesh_IncrementalMesh(shape, 0.005, false, 0.1, true);
679
return BRep_Tool::Polygon3D(TopoDS::Edge(shape), tmp);
685
void getNormalBySLProp(T& prop, double u, double v, Standard_Real lastU, Standard_Real lastV,
686
const Standard_Real tol, gp_Dir& dir, Standard_Boolean& done)
688
if (prop.D1U().Magnitude() > tol &&
689
prop.D1V().Magnitude() > tol &&
690
prop.IsNormalDefined()) {
692
done = Standard_True;
696
CSLib_NormalStatus stat;
697
CSLib::Normal(prop.D1U(), prop.D1V(), prop.D2U(), prop.D2V(), prop.DUV(),
698
tol, done, stat, dir);
701
if (stat == CSLib_D1NuIsNull) {
702
if (Abs(lastV - v) < tol)
705
else if (stat == CSLib_D1NvIsNull || stat == CSLib_D1NuIsParallelD1Nv) {
706
if (Abs(lastU - u) < tol)
712
void Part::Tools::getNormal(const Handle(Geom_Surface)& surf, double u, double v,
713
const Standard_Real tol, gp_Dir& dir, Standard_Boolean& done)
715
GeomLProp_SLProps prop(surf, u, v, 1, tol);
716
Standard_Real u1,u2,v1,v2;
717
surf->Bounds(u1,u2,v1,v2);
719
getNormalBySLProp<GeomLProp_SLProps>(prop, u, v, u2, v2, tol, dir, done);
722
void Part::Tools::getNormal(const TopoDS_Face& face, double u, double v,
723
const Standard_Real tol, gp_Dir& dir, Standard_Boolean& done)
725
BRepAdaptor_Surface adapt(face);
726
BRepLProp_SLProps prop(adapt, u, v, 1, tol);
727
Standard_Real u2 = adapt.LastUParameter();
728
Standard_Real v2 = adapt.LastVParameter();
730
getNormalBySLProp<BRepLProp_SLProps>(prop, u, v, u2, v2, tol, dir, done);
732
if (face.Orientation() == TopAbs_REVERSED)
736
TopLoc_Location Part::Tools::fromPlacement(const Base::Placement& plm)
738
Base::Rotation r = plm.getRotation();
739
double q1, q2, q3, q4;
740
r.getValue(q1, q2, q3, q4);
741
Base::Vector3d t = plm.getPosition();
744
trf.SetTransformation(gp_Quaternion(q1, q2, q3, q4), gp_Vec(t.x, t.y, t.z));