1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
24 #include <GEOMUtils_Hatcher.hxx>
26 #include <BRep_Tool.hxx>
27 #include <BRepTools.hxx>
28 #include <Geom2d_Line.hxx>
29 #include <Geom2d_TrimmedCurve.hxx>
30 #include <Geom2dAdaptor_Curve.hxx>
31 #include <TopExp_Explorer.hxx>
33 #include <TopoDS_Edge.hxx>
34 #include <HatchGen_Domain.hxx>
37 static Standard_Real IntersectorConfusion = 1.e-10; // -8;
38 static Standard_Real IntersectorTangency = 1.e-10; // -8;
39 static Standard_Real HatcherConfusion2d = 1.e-8;
40 static Standard_Real HatcherConfusion3d = 1.e-8;
41 // VTK uses float numbers - Precision::Infinite() is double and
42 // can not be accepted.
43 static float InfiniteValue = 1e38;
45 //=======================================================================
46 //function : GEOMUtils_Hatcher
48 //=======================================================================
49 GEOMUtils::Hatcher::Hatcher(const TopoDS_Face &theFace)
50 : myHatcher(Geom2dHatch_Intersector (IntersectorConfusion, IntersectorTangency),
51 HatcherConfusion2d, HatcherConfusion3d,
52 Standard_True, Standard_False),
54 myIsDone (Standard_False),
61 BRepTools::UVBounds (theFace, myUMin, myUMax, myVMin, myVMax);
63 Standard_Boolean InfiniteUMin = Precision::IsNegativeInfinite (myUMin);
64 Standard_Boolean InfiniteUMax = Precision::IsPositiveInfinite (myUMax);
65 Standard_Boolean InfiniteVMin = Precision::IsNegativeInfinite (myVMin);
66 Standard_Boolean InfiniteVMax = Precision::IsPositiveInfinite (myVMax);
68 if (InfiniteUMin && InfiniteUMax) {
69 myUMin = - InfiniteValue;
70 myUMax = InfiniteValue;
71 } else if (InfiniteUMin) {
72 myUMin = myUMax - InfiniteValue;
73 } else if (InfiniteUMax) {
74 myUMax = myUMin + InfiniteValue;
77 if (InfiniteVMin && InfiniteVMax) {
78 myVMin = - InfiniteValue;
79 myVMax = InfiniteValue;
80 } else if (InfiniteVMin) {
81 myVMin = myVMax - InfiniteValue;
82 } else if (InfiniteVMax) {
83 myVMax = myVMin + InfiniteValue;
87 TopExp_Explorer anExpEdges(theFace, TopAbs_EDGE);
88 const Standard_Real aParamTol = Precision::PConfusion();
90 for (; anExpEdges.More(); anExpEdges.Next()) {
91 const TopoDS_Edge& anEdge = TopoDS::Edge (anExpEdges.Current());
93 const Handle(Geom2d_Curve) PCurve =
94 BRep_Tool::CurveOnSurface (anEdge, theFace, U1, U2);
96 if (PCurve.IsNull()) {
104 //-- Test if a TrimmedCurve is necessary
105 if(Abs(PCurve->FirstParameter() - U1) <= aParamTol &&
106 Abs(PCurve->LastParameter() - U2) <= aParamTol) {
107 myHatcher.AddElement(PCurve, anEdge.Orientation());
109 if (!PCurve->IsPeriodic()) {
110 Handle(Geom2d_TrimmedCurve) TrimPCurve =
111 Handle(Geom2d_TrimmedCurve)::DownCast(PCurve);
113 if (!TrimPCurve.IsNull()) {
114 Handle(Geom2d_Curve) aBasisCurve = TrimPCurve->BasisCurve();
116 if (aBasisCurve->FirstParameter() - U1 > aParamTol ||
117 U2 - aBasisCurve->LastParameter() > aParamTol) {
118 myHatcher.AddElement (PCurve, anEdge.Orientation());
122 if (PCurve->FirstParameter() - U1 > aParamTol) {
123 U1 = PCurve->FirstParameter();
125 if (U2 - PCurve->LastParameter() > aParamTol) {
126 U2=PCurve->LastParameter();
131 Handle (Geom2d_TrimmedCurve) TrimPCurve =
132 new Geom2d_TrimmedCurve (PCurve, U1, U2);
134 myHatcher.AddElement (TrimPCurve, anEdge.Orientation());
139 //=======================================================================
142 //=======================================================================
143 void GEOMUtils::Hatcher::Init(const Standard_Integer theNbIsos)
145 Init(theNbIsos, theNbIsos);
148 //=======================================================================
151 //=======================================================================
152 void GEOMUtils::Hatcher::Init(const Standard_Integer theNbIsoU,
153 const Standard_Integer theNbIsoV)
158 if (theNbIsoU > 0 || theNbIsoV > 0) {
159 Standard_Integer IIso;
160 Standard_Real DeltaU = Abs (myUMax - myUMin);
161 Standard_Real DeltaV = Abs (myVMax - myVMin);
162 Standard_Real confusion = Min (DeltaU, DeltaV) * myHatcher.Confusion3d();
164 myHatcher.Confusion3d (confusion);
167 myUPrm = new TColStd_HArray1OfReal (1, theNbIsoU);
168 myUInd = new TColStd_HArray1OfInteger(1, theNbIsoU, 0);
170 Standard_Real StepU = DeltaU / (Standard_Real) theNbIsoU;
172 if (StepU > confusion) {
173 Standard_Real UPrm = myUMin + StepU / 2.;
174 gp_Dir2d Dir (0., 1.);
176 for (IIso = 1; IIso <= theNbIsoU; IIso++) {
177 myUPrm->SetValue(IIso, UPrm);
178 gp_Pnt2d Ori (UPrm, 0.);
179 Geom2dAdaptor_Curve HCur (new Geom2d_Line (Ori, Dir));
180 myUInd->SetValue(IIso, myHatcher.AddHatching(HCur));
187 myVPrm = new TColStd_HArray1OfReal (1, theNbIsoV);
188 myVInd = new TColStd_HArray1OfInteger(1, theNbIsoV, 0);
190 Standard_Real StepV = DeltaV / (Standard_Real) theNbIsoV;
192 if (StepV > confusion) {
193 Standard_Real VPrm = myVMin + StepV / 2.;
194 gp_Dir2d Dir (1., 0.);
196 for (IIso = 1; IIso <= theNbIsoV; IIso++) {
197 myVPrm->SetValue(IIso, VPrm);
198 gp_Pnt2d Ori (0., VPrm);
199 Geom2dAdaptor_Curve HCur (new Geom2d_Line (Ori, Dir));
200 myVInd->SetValue(IIso, myHatcher.AddHatching(HCur));
208 //=======================================================================
211 //=======================================================================
212 void GEOMUtils::Hatcher::Init(const GeomAbs_IsoType theIsoType,
213 const Standard_Real theParameter)
218 if (theIsoType == GeomAbs_IsoU || theIsoType == GeomAbs_IsoV) {
219 const Standard_Boolean isIsoU = (theIsoType == GeomAbs_IsoU);
220 Handle(TColStd_HArray1OfReal) &aPrm = (isIsoU ? myUPrm : myVPrm);
221 Handle(TColStd_HArray1OfInteger) &anInd = (isIsoU ? myUInd : myVInd);
222 Handle(Geom2d_Line) aLine;
224 aPrm = new TColStd_HArray1OfReal (1, 1);
225 anInd = new TColStd_HArray1OfInteger(1, 1);
226 aPrm->SetValue(1, theParameter);
230 gp_Dir2d aDir (0., 1.);
231 gp_Pnt2d anOri(theParameter, 0.);
233 aLine = new Geom2d_Line(anOri, aDir);
236 gp_Dir2d aDir (1., 0.);
237 gp_Pnt2d anOri(0., theParameter);
239 aLine = new Geom2d_Line(anOri, aDir);
242 Geom2dAdaptor_Curve aGACurve (aLine);
244 anInd->SetValue(1, myHatcher.AddHatching(aGACurve));
248 //=======================================================================
251 //=======================================================================
252 void GEOMUtils::Hatcher::Perform()
258 Standard_Integer anIndex;
260 if (myUInd.IsNull() == Standard_False) {
261 for (i = myUInd->Lower() ; i <= myUInd->Upper() ; i++) {
262 anIndex = myUInd->Value(i);
265 if (myHatcher.TrimDone(anIndex) && !myHatcher.TrimFailed(anIndex)) {
266 myHatcher.ComputeDomains(anIndex);
269 myIsDone = (myHatcher.NbDomains(anIndex) > 0);
276 if (myVInd.IsNull() == Standard_False) {
277 for (i = myVInd->Lower() ; i <= myVInd->Upper() ; i++) {
278 anIndex = myVInd->Value(i);
281 if (myHatcher.TrimDone(anIndex) && !myHatcher.TrimFailed(anIndex)) {
282 myHatcher.ComputeDomains(anIndex);
285 myIsDone = (myHatcher.NbDomains(anIndex) > 0);
293 //=======================================================================
294 //function : GetNbDomains
296 //=======================================================================
297 Standard_Integer GEOMUtils::Hatcher::GetNbDomains
298 (const Standard_Integer theHatchingIndex) const
300 Standard_Integer aResult = -1;
302 if (myIsDone && myHatcher.IsDone(theHatchingIndex)) {
303 aResult = myHatcher.NbDomains(theHatchingIndex);
309 //=======================================================================
310 //function : GetDomain
312 //=======================================================================
313 Standard_Boolean GEOMUtils::Hatcher::GetDomain
314 (const Standard_Integer theHatchingIndex,
315 const Standard_Integer theDomainIndex,
316 Standard_Real &theParam1,
317 Standard_Real &theParam2) const
319 Standard_Boolean isOK = Standard_False;
321 if (theDomainIndex > 0) {
322 const Standard_Integer aNbDomains = GetNbDomains(theHatchingIndex);
324 if (theDomainIndex <= aNbDomains) {
325 const HatchGen_Domain& aDomain =
326 myHatcher.Domain (theHatchingIndex, theDomainIndex);
328 if (aDomain.HasFirstPoint()) {
329 theParam1 = aDomain.FirstPoint().Parameter();
331 theParam1 = myVMin - InfiniteValue;
334 if (aDomain.HasSecondPoint()) {
335 theParam2 = aDomain.SecondPoint().Parameter();
337 theParam2 = myVMax + InfiniteValue;
340 isOK = Standard_True;
347 //=======================================================================
348 //function : IsDomainInfinite
350 //=======================================================================
351 Standard_Boolean GEOMUtils::Hatcher::IsDomainInfinite
352 (const Standard_Integer theHatchingIndex,
353 const Standard_Integer theDomainIndex) const
355 Standard_Boolean isInfinite = Standard_False;
357 if (theDomainIndex > 0) {
358 const Standard_Integer aNbDomains = GetNbDomains(theHatchingIndex);
360 if (theDomainIndex <= aNbDomains) {
361 const HatchGen_Domain& aDomain =
362 myHatcher.Domain (theHatchingIndex, theDomainIndex);
364 if (!aDomain.HasFirstPoint() || !aDomain.HasSecondPoint()) {
365 isInfinite = Standard_True;
373 //=======================================================================
374 //function : GetHatching
376 //=======================================================================
377 const Handle(Geom2d_Curve) &GEOMUtils::Hatcher::GetHatching
378 (const Standard_Integer theHatchingIndex) const
380 const Geom2dAdaptor_Curve &aGACurve =
381 myHatcher.HatchingCurve(theHatchingIndex);
383 return aGACurve.Curve();
386 //=======================================================================
389 //=======================================================================
390 void GEOMUtils::Hatcher::Clear()
392 myIsDone = Standard_False;
397 myHatcher.ClrHatchings();