0024282: Shaded presentation is not computed due to exception in StdPrs_ToolShadedSha...
[occt.git] / src / StdPrs / StdPrs_ToolShadedShape.cxx
CommitLineData
b311480e 1// Created on: 1993-10-27
2// Created by: Jean-LOuis FRENKEL
3// Copyright (c) 1993-1999 Matra Datavision
4// Copyright (c) 1999-2012 OPEN CASCADE SAS
5//
6// The content of this file is subject to the Open CASCADE Technology Public
7// License Version 6.5 (the "License"). You may not use the content of this file
8// except in compliance with the License. Please obtain a copy of the License
9// at http://www.opencascade.org and read it completely before using this file.
10//
11// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13//
14// The Original Code and all software distributed under the License is
15// distributed on an "AS IS" basis, without warranty of any kind, and the
16// Initial Developer hereby disclaims all such warranties, including without
17// limitation, any warranties of merchantability, fitness for a particular
18// purpose or non-infringement. Please see the License for the specific terms
19// and conditions governing the rights and limitations under the License.
20
7fd59977 21#include <StdPrs_ToolShadedShape.ixx>
9447f912 22
23#include <BRep_Tool.hxx>
24#include <BRepAdaptor_Surface.hxx>
25#include <GeomAbs_SurfaceType.hxx>
26#include <GeomLib.hxx>
27#include <gp_Vec.hxx>
28#include <Poly_Connect.hxx>
7fd59977 29#include <Poly_Triangulation.hxx>
9447f912 30#include <Precision.hxx>
7fd59977 31#include <TColgp_HArray1OfPnt.hxx>
32#include <TColgp_Array1OfPnt.hxx>
33#include <TColgp_Array1OfPnt2d.hxx>
7fd59977 34#include <TopAbs_Orientation.hxx>
7fd59977 35#include <TopLoc_Location.hxx>
36#include <TShort_HArray1OfShortReal.hxx>
37#include <TShort_Array1OfShortReal.hxx>
38
39//=======================================================================
40//function : IsClosed
9447f912 41//purpose :
7fd59977 42//=======================================================================
9447f912 43Standard_Boolean StdPrs_ToolShadedShape::IsClosed (const TopoDS_Shape& theShape)
7fd59977 44{
9447f912 45 return theShape.Closed();
7fd59977 46}
47
7fd59977 48//=======================================================================
49//function : Triangulation
9447f912 50//purpose :
7fd59977 51//=======================================================================
9447f912 52Handle(Poly_Triangulation) StdPrs_ToolShadedShape::Triangulation (const TopoDS_Face& theFace,
53 TopLoc_Location& theLoc)
7fd59977 54{
9447f912 55 return BRep_Tool::Triangulation (theFace, theLoc);
7fd59977 56}
57
7fd59977 58//=======================================================================
59//function : Normal
9447f912 60//purpose :
7fd59977 61//=======================================================================
9447f912 62void StdPrs_ToolShadedShape::Normal (const TopoDS_Face& theFace,
63 Poly_Connect& thePolyConnect,
64 TColgp_Array1OfDir& theNormals)
7fd59977 65{
9447f912 66 const Handle(Poly_Triangulation)& aPolyTri = thePolyConnect.Triangulation();
67 const TColgp_Array1OfPnt& aNodes = aPolyTri->Nodes();
68 if (aPolyTri->HasNormals())
69 {
70 // normals pre-computed in triangulation structure
71 const TShort_Array1OfShortReal& aNormals = aPolyTri->Normals();
72 const Standard_ShortReal* aNormArr = &(aNormals.Value (aNormals.Lower()));
73 for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
74 {
75 const Standard_Integer anId = 3 * (aNodeIter - aNodes.Lower());
76 const gp_Dir aNorm (aNormArr[anId + 0],
77 aNormArr[anId + 1],
78 aNormArr[anId + 2]);
79 theNormals (aNodeIter) = aNorm;
7fd59977 80 }
81
9447f912 82 if (theFace.Orientation() == TopAbs_REVERSED)
83 {
84 for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
85 {
86 theNormals.ChangeValue (aNodeIter).Reverse();
7fd59977 87 }
88 }
9447f912 89 return;
7fd59977 90 }
7fd59977 91
9447f912 92 // take in face the surface location
93 const TopoDS_Face aZeroFace = TopoDS::Face (theFace.Located (TopLoc_Location()));
94 Handle(Geom_Surface) aSurf = BRep_Tool::Surface (aZeroFace);
95 const Standard_Real aTol = Precision::Confusion();
96 Handle(TShort_HArray1OfShortReal) aNormals = new TShort_HArray1OfShortReal (1, aPolyTri->NbNodes() * 3);
97 const Poly_Array1OfTriangle& aTriangles = aPolyTri->Triangles();
98 const TColgp_Array1OfPnt2d* aNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull()
99 ? &aPolyTri->UVNodes()
100 : NULL;
101 Standard_Integer aTri[3];
102 for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
103 {
104 // try to retrieve normal from real surface first, when UV coordinates are available
105 if (aNodesUV == NULL
106 || GeomLib::NormEstim (aSurf, aNodesUV->Value (aNodeIter), aTol, theNormals (aNodeIter)) > 1)
107 {
108 // compute flat normals
109 gp_XYZ eqPlan (0.0, 0.0, 0.0);
110 for (thePolyConnect.Initialize (aNodeIter); thePolyConnect.More(); thePolyConnect.Next())
111 {
112 aTriangles (thePolyConnect.Value()).Get (aTri[0], aTri[1], aTri[2]);
113 const gp_XYZ v1 (aNodes (aTri[1]).Coord() - aNodes (aTri[0]).Coord());
114 const gp_XYZ v2 (aNodes (aTri[2]).Coord() - aNodes (aTri[1]).Coord());
115 const gp_XYZ vv = v1 ^ v2;
116 const Standard_Real aMod = vv.Modulus();
117 if (aMod >= aTol)
118 {
119 eqPlan += vv / aMod;
120 }
7fd59977 121 }
9447f912 122 const Standard_Real aModMax = eqPlan.Modulus();
123 theNormals (aNodeIter) = (aModMax > aTol) ? gp_Dir (eqPlan) : gp::DZ();
7fd59977 124 }
125
9447f912 126 const Standard_Integer anId = (aNodeIter - aNodes.Lower()) * 3;
127 aNormals->SetValue (anId + 1, (Standard_ShortReal )theNormals (aNodeIter).X());
128 aNormals->SetValue (anId + 2, (Standard_ShortReal )theNormals (aNodeIter).Y());
129 aNormals->SetValue (anId + 3, (Standard_ShortReal )theNormals (aNodeIter).Z());
7fd59977 130 }
9447f912 131 aPolyTri->SetNormals (aNormals);
7fd59977 132
9447f912 133 if (theFace.Orientation() == TopAbs_REVERSED)
134 {
135 for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
136 {
137 theNormals.ChangeValue (aNodeIter).Reverse();
7fd59977 138 }
7fd59977 139 }
7fd59977 140}