1 // Created on: 1993-10-27
2 // Created by: Jean-LOuis FRENKEL
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <StdPrs_ToolShadedShape.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepAdaptor_Surface.hxx>
21 #include <GeomAbs_SurfaceType.hxx>
22 #include <GeomLib.hxx>
24 #include <Poly_Connect.hxx>
25 #include <Poly_Triangulation.hxx>
26 #include <Precision.hxx>
27 #include <TColgp_HArray1OfPnt.hxx>
28 #include <TColgp_Array1OfPnt.hxx>
29 #include <TColgp_Array1OfPnt2d.hxx>
30 #include <TopAbs_Orientation.hxx>
31 #include <TopLoc_Location.hxx>
32 #include <TShort_HArray1OfShortReal.hxx>
33 #include <TShort_Array1OfShortReal.hxx>
34 #include <TColgp_Array1OfDir.hxx>
35 #include <TopExp_Explorer.hxx>
38 //=======================================================================
39 //function : isTriangulated
41 //=======================================================================
42 Standard_Boolean StdPrs_ToolShadedShape::IsTriangulated (const TopoDS_Shape& theShape)
44 TopLoc_Location aLocDummy;
45 for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
47 const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
48 const Handle(Poly_Triangulation)& aTri = BRep_Tool::Triangulation (aFace, aLocDummy);
51 return Standard_False;
57 //=======================================================================
60 //=======================================================================
61 Standard_Boolean StdPrs_ToolShadedShape::IsClosed (const TopoDS_Shape& theShape)
63 if (theShape.IsNull())
68 switch (theShape.ShapeType())
71 case TopAbs_COMPSOLID:
74 // check that compound consists of closed solids
75 for (TopoDS_Iterator anIter (theShape); anIter.More(); anIter.Next())
77 const TopoDS_Shape& aShape = anIter.Value();
78 if (!IsClosed (aShape))
80 return Standard_False;
87 // Check for non-manifold topology first of all:
88 // have to use BRep_Tool::IsClosed() because it checks the face connectivity
90 if (!BRep_Tool::IsClosed (theShape))
91 return Standard_False;
93 for (TopoDS_Iterator anIter (theShape); anIter.More(); anIter.Next())
95 const TopoDS_Shape& aShape = anIter.Value();
101 if (aShape.ShapeType() == TopAbs_FACE)
104 return Standard_False;
106 else if (!IsTriangulated (aShape))
108 // mesh contains holes
109 return Standard_False;
112 return Standard_True;
117 // free faces / shell are not allowed
118 return Standard_False;
125 return Standard_True;
130 //=======================================================================
131 //function : Triangulation
133 //=======================================================================
134 Handle(Poly_Triangulation) StdPrs_ToolShadedShape::Triangulation (const TopoDS_Face& theFace,
135 TopLoc_Location& theLoc)
137 return BRep_Tool::Triangulation (theFace, theLoc);
140 //=======================================================================
143 //=======================================================================
144 void StdPrs_ToolShadedShape::Normal (const TopoDS_Face& theFace,
145 Poly_Connect& thePolyConnect,
146 TColgp_Array1OfDir& theNormals)
148 const Handle(Poly_Triangulation)& aPolyTri = thePolyConnect.Triangulation();
149 const TColgp_Array1OfPnt& aNodes = aPolyTri->Nodes();
150 if (aPolyTri->HasNormals())
152 // normals pre-computed in triangulation structure
153 const TShort_Array1OfShortReal& aNormals = aPolyTri->Normals();
154 const Standard_ShortReal* aNormArr = &(aNormals.Value (aNormals.Lower()));
155 for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
157 const Standard_Integer anId = 3 * (aNodeIter - aNodes.Lower());
158 const gp_Dir aNorm (aNormArr[anId + 0],
161 theNormals (aNodeIter) = aNorm;
164 if (theFace.Orientation() == TopAbs_REVERSED)
166 for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
168 theNormals.ChangeValue (aNodeIter).Reverse();
174 // take in face the surface location
175 const TopoDS_Face aZeroFace = TopoDS::Face (theFace.Located (TopLoc_Location()));
176 Handle(Geom_Surface) aSurf = BRep_Tool::Surface (aZeroFace);
177 const Standard_Real aTol = Precision::Confusion();
178 Handle(TShort_HArray1OfShortReal) aNormals = new TShort_HArray1OfShortReal (1, aPolyTri->NbNodes() * 3);
179 const Poly_Array1OfTriangle& aTriangles = aPolyTri->Triangles();
180 const TColgp_Array1OfPnt2d* aNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull()
181 ? &aPolyTri->UVNodes()
183 Standard_Integer aTri[3];
184 for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
186 // try to retrieve normal from real surface first, when UV coordinates are available
188 || GeomLib::NormEstim (aSurf, aNodesUV->Value (aNodeIter), aTol, theNormals (aNodeIter)) > 1)
190 // compute flat normals
191 gp_XYZ eqPlan (0.0, 0.0, 0.0);
192 for (thePolyConnect.Initialize (aNodeIter); thePolyConnect.More(); thePolyConnect.Next())
194 aTriangles (thePolyConnect.Value()).Get (aTri[0], aTri[1], aTri[2]);
195 const gp_XYZ v1 (aNodes (aTri[1]).Coord() - aNodes (aTri[0]).Coord());
196 const gp_XYZ v2 (aNodes (aTri[2]).Coord() - aNodes (aTri[1]).Coord());
197 const gp_XYZ vv = v1 ^ v2;
198 const Standard_Real aMod = vv.Modulus();
204 const Standard_Real aModMax = eqPlan.Modulus();
205 theNormals (aNodeIter) = (aModMax > aTol) ? gp_Dir (eqPlan) : gp::DZ();
208 const Standard_Integer anId = (aNodeIter - aNodes.Lower()) * 3;
209 aNormals->SetValue (anId + 1, (Standard_ShortReal )theNormals (aNodeIter).X());
210 aNormals->SetValue (anId + 2, (Standard_ShortReal )theNormals (aNodeIter).Y());
211 aNormals->SetValue (anId + 3, (Standard_ShortReal )theNormals (aNodeIter).Z());
213 aPolyTri->SetNormals (aNormals);
215 if (theFace.Orientation() == TopAbs_REVERSED)
217 for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
219 theNormals.ChangeValue (aNodeIter).Reverse();