Salome HOME
Fix of searching for shapes on surface (NGO letter from 20.02.2015)
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_FinderShapeOn2.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File:        GEOMAlgo_FinderShapeOn2.cxx
24 // Created:     Fri Mar  4 10:31:06 2005
25 // Author:      Peter KURNEV
26 //              <pkv@irinox>
27 //
28 #include <GEOMAlgo_FinderShapeOn2.hxx>
29 #include <GEOMAlgo_DataMapIteratorOfDataMapOfPassKeyInteger.hxx>
30 #include <GEOMAlgo_DataMapOfPassKeyInteger.hxx>
31 #include <GEOMAlgo_ListIteratorOfListOfPnt.hxx>
32 #include <GEOMAlgo_PassKey.hxx>
33 #include <GEOMAlgo_StateCollector.hxx>
34 #include <GEOMAlgo_SurfaceTools.hxx>
35
36 #include <Bnd_Box.hxx>
37 #include <BRep_Tool.hxx>
38 #include <BRepBndLib.hxx>
39 #include <BRepMesh_IncrementalMesh.hxx>
40 #include <BRepTools.hxx>
41 #include <Geom_Curve.hxx>
42 #include <Geom_Surface.hxx>
43 #include <Geom2d_Line.hxx>
44 #include <Geom2dAdaptor_Curve.hxx>
45 #include <Geom2dHatch_Hatcher.hxx>
46 #include <gp_Dir2d.hxx>
47 #include <gp_Pnt2d.hxx>
48 #include <gp_Pnt.hxx>
49 #include <gp_Trsf.hxx>
50 #include <HatchGen_Domain.hxx>
51 #include <IntTools_Tools.hxx>
52 #include <Poly_Array1OfTriangle.hxx>
53 #include <Poly_Polygon3D.hxx>
54 #include <Poly_PolygonOnTriangulation.hxx>
55 #include <Poly_Triangle.hxx>
56 #include <Poly_Triangulation.hxx>
57 #include <Precision.hxx>
58 #include <TColgp_Array1OfPnt.hxx>
59 #include <TColStd_Array1OfInteger.hxx>
60 #include <TColStd_MapOfInteger.hxx>
61 #include <TopAbs_State.hxx>
62 #include <TopExp.hxx>
63 #include <TopExp_Explorer.hxx>
64 #include <TopLoc_Location.hxx>
65 #include <TopoDS.hxx>
66 #include <TopoDS_Edge.hxx>
67 #include <TopoDS_Face.hxx>
68 #include <TopoDS_Shape.hxx>
69 #include <TopoDS_Vertex.hxx>
70 #include <TopTools_IndexedMapOfShape.hxx>
71
72 #if OCC_VERSION_LARGE > 0x06070100
73 #include <IntTools_Context.hxx>
74 #else
75 #include <BOPInt_Context.hxx>
76 #endif
77
78 //=======================================================================
79 //function : 
80 //purpose  :
81 //=======================================================================
82 GEOMAlgo_FinderShapeOn2::GEOMAlgo_FinderShapeOn2()
83 :
84   GEOMAlgo_ShapeAlgo()
85 {
86   myTolerance=0.0001;
87   myShapeType=TopAbs_VERTEX;
88   myState=GEOMAlgo_ST_UNKNOWN;
89   myNbPntsMin=3;
90   myNbPntsMax=0;
91 }
92 //=======================================================================
93 //function : ~
94 //purpose  :
95 //=======================================================================
96 GEOMAlgo_FinderShapeOn2::~GEOMAlgo_FinderShapeOn2()
97 {
98 }
99 //=======================================================================
100 //function : SetClsf
101 //purpose  :
102 //=======================================================================
103 void GEOMAlgo_FinderShapeOn2::SetClsf(const Handle(GEOMAlgo_Clsf)& aClsf)
104 {
105   myClsf=aClsf;
106 }
107 //=======================================================================
108 //function : Clsf
109 //purpose  :
110 //=======================================================================
111 const Handle(GEOMAlgo_Clsf)& GEOMAlgo_FinderShapeOn2::Clsf() const
112 {
113   return myClsf;
114 }
115 //=======================================================================
116 //function : SetShapeType
117 //purpose  :
118 //=======================================================================
119 void GEOMAlgo_FinderShapeOn2::SetShapeType(const TopAbs_ShapeEnum aType)
120 {
121   myShapeType=aType;
122 }
123 //=======================================================================
124 //function : ShapeType
125 //purpose  :
126 //=======================================================================
127 TopAbs_ShapeEnum GEOMAlgo_FinderShapeOn2::ShapeType()const
128 {
129   return myShapeType;
130 }
131 //=======================================================================
132 //function : SetState
133 //purpose  :
134 //=======================================================================
135 void GEOMAlgo_FinderShapeOn2::SetState(const GEOMAlgo_State aState)
136 {
137   myState=aState;
138 }
139 //=======================================================================
140 //function : State
141 //purpose  :
142 //=======================================================================
143 GEOMAlgo_State GEOMAlgo_FinderShapeOn2::State() const
144 {
145   return myState;
146 }
147 //=======================================================================
148 //function : SetNbPntsMin
149 //purpose  :
150 //=======================================================================
151 void GEOMAlgo_FinderShapeOn2::SetNbPntsMin(const Standard_Integer aNb)
152 {
153   myNbPntsMin=aNb;
154 }
155 //=======================================================================
156 //function : NbPntsMin
157 //purpose  :
158 //=======================================================================
159 Standard_Integer GEOMAlgo_FinderShapeOn2::NbPntsMin()const
160 {
161   return myNbPntsMin;
162 }
163 //=======================================================================
164 //function : SetNbPntsMax
165 //purpose  :
166 //=======================================================================
167 void GEOMAlgo_FinderShapeOn2::SetNbPntsMax(const Standard_Integer aNb)
168 {
169   myNbPntsMax=aNb;
170 }
171 //=======================================================================
172 //function : NbPntsMax
173 //purpose  :
174 //=======================================================================
175 Standard_Integer GEOMAlgo_FinderShapeOn2::NbPntsMax()const
176 {
177   return myNbPntsMax;
178 }
179 //=======================================================================
180 // function: MSS
181 // purpose:
182 //=======================================================================
183   const GEOMAlgo_IndexedDataMapOfShapeState& GEOMAlgo_FinderShapeOn2::MSS() const
184 {
185   return myMSS;
186 }
187 //=======================================================================
188 // function: Shapes
189 // purpose:
190 //=======================================================================
191 const TopTools_ListOfShape& GEOMAlgo_FinderShapeOn2::Shapes() const
192 {
193   Standard_Integer i, aNb;
194   TopTools_ListOfShape* pL;
195   //
196   pL=(TopTools_ListOfShape*) &myLS;
197   pL->Clear();
198   //
199   aNb=myMSS.Extent();
200   for (i=1; i<=aNb; ++i) {
201     const TopoDS_Shape& aS=myMSS.FindKey(i);
202     if (aS.ShapeType()==myShapeType) {
203       pL->Append(aS);
204     }
205   }
206   return myLS;
207 }
208 //=======================================================================
209 //function : Perform
210 //purpose  :
211 //=======================================================================
212 void GEOMAlgo_FinderShapeOn2::Perform()
213 {
214   myErrorStatus=0;
215   myWarningStatus=0;
216   myLS.Clear();
217   myMSS.Clear();
218   //
219   CheckData();
220   if(myErrorStatus) {
221     return;
222   }
223   //
224   // Initialize the context
225   GEOMAlgo_ShapeAlgo::Perform();
226   //
227   myClsf->SetTolerance(myTolerance);
228   //
229   // 1
230   ProcessVertices();
231   if(myErrorStatus) {
232     return;
233   }
234   if (myShapeType==TopAbs_VERTEX) {
235     return;
236   }
237   //
238   // 2
239   ProcessEdges();
240   if(myErrorStatus) {
241     return;
242   }
243   if (myShapeType==TopAbs_EDGE) {
244     return;
245   }
246   //
247   // 3
248   ProcessFaces();
249   if(myErrorStatus) {
250     return;
251   }
252   if (myShapeType==TopAbs_FACE) {
253     return;
254   }
255   //
256   // 4
257   ProcessSolids();
258   //
259 }
260 //=======================================================================
261 //function : CheckData
262 //purpose  :
263 //=======================================================================
264 void GEOMAlgo_FinderShapeOn2::CheckData()
265 {
266   Standard_Integer iErr;
267   //
268   myErrorStatus=0;
269   //
270   if(myClsf.IsNull()) {
271     myErrorStatus=10; // myClsf=NULL
272     return;
273   }
274   //
275   myClsf->CheckData();
276   iErr=myClsf->ErrorStatus();
277   if (iErr) {
278     myErrorStatus=41; // invalid data for classifier
279     return;
280   }
281   //
282   if (myShape.IsNull()) {
283     myErrorStatus=11; // myShape=NULL
284     return;
285   }
286   //
287   if (!(myShapeType==TopAbs_VERTEX ||
288         myShapeType==TopAbs_EDGE ||
289         myShapeType==TopAbs_FACE ||
290         myShapeType==TopAbs_SOLID)) {
291     myErrorStatus=12; // unallowed sub-shape type
292     return;
293   }
294   //
295   if (myState==GEOMAlgo_ST_UNKNOWN ||
296       myState==GEOMAlgo_ST_INOUT) {
297     myErrorStatus=13; // unallowed state type
298     return;
299   }
300 }
301 //=======================================================================
302 //function : ProcessVertices
303 //purpose  :
304 //=======================================================================
305 void GEOMAlgo_FinderShapeOn2::ProcessVertices()
306 {
307   myErrorStatus=0;
308   //
309   Standard_Boolean bIsConformState;
310   Standard_Integer i, aNb, iErr;
311   gp_Pnt aP;
312   TopTools_IndexedMapOfShape aM;
313   TopAbs_State aSt;
314   //
315   TopExp::MapShapes(myShape, TopAbs_VERTEX, aM);
316   aNb=aM.Extent();
317   for (i=1; i<=aNb; ++i) {
318     const TopoDS_Vertex& aV=TopoDS::Vertex(aM(i));
319     aP=BRep_Tool::Pnt(aV);
320     //
321     myClsf->SetPnt(aP);
322     myClsf->Perform();
323     iErr=myClsf->ErrorStatus();
324     if (iErr) {
325       myErrorStatus=40; // point can not be classified
326       return;
327     }
328     //
329     aSt=myClsf->State();
330     bIsConformState=GEOMAlgo_SurfaceTools::IsConformState(aSt, myState);
331     //
332     if (myShapeType==TopAbs_VERTEX){
333       if (bIsConformState) {
334         myMSS.Add(aV, aSt);
335       }
336     }
337     else if (bIsConformState || aSt==TopAbs_ON) {
338       myMSS.Add(aV, aSt);
339     }
340   }
341 }
342 //=======================================================================
343 //function : ProcessEdges
344 //purpose  :
345 //=======================================================================
346 void GEOMAlgo_FinderShapeOn2::ProcessEdges()
347 {
348   myErrorStatus=0;
349   //
350   Standard_Boolean bIsConformState, bIsToBreak;
351   Standard_Integer i, aNb, iCnt, iErr;
352   TopAbs_State aSt;
353   TopTools_IndexedMapOfShape aM;
354   TopExp_Explorer aExp;
355   GEOMAlgo_ListIteratorOfListOfPnt aIt;
356   //
357   TopExp::MapShapes(myShape, TopAbs_EDGE, aM);
358   aNb=aM.Extent();
359   for (i=1; i<=aNb; ++i) {
360     GEOMAlgo_ListOfPnt aLP;
361     GEOMAlgo_StateCollector aSC;
362     //
363     const TopoDS_Edge& aE=TopoDS::Edge(aM(i));
364     //
365     aExp.Init(aE, TopAbs_VERTEX);
366     for (; aExp.More(); aExp.Next()) {
367       const TopoDS_Shape& aV=aExp.Current();
368       //
369       bIsConformState=myMSS.Contains(aV);
370       if (!bIsConformState) {
371         break;// vertex has non-conformed state
372       }
373       else {
374         aSt=myMSS.FindFromKey(aV);
375         aSC.AppendState(aSt);
376       }
377     }
378     //
379     if (!bIsConformState) {
380       continue; // vertex has non-conformed state,skip edge
381     }
382     //
383     if (BRep_Tool::Degenerated(aE)) {
384       myMSS.Add(aE, aSt);
385       continue;
386     }
387     //
388     if (myState==GEOMAlgo_ST_ON) {
389       Standard_Boolean bCanBeON;
390       Standard_Real aT1, aT2;
391       Handle(Geom_Curve) aC;
392       //
393       aC=BRep_Tool::Curve(aE, aT1, aT2);
394       bCanBeON=myClsf->CanBeON(aC);
395       if(!bCanBeON) {
396         continue;
397       }
398     }
399     //
400     InnerPoints(aE, aLP);
401     if (myErrorStatus) {
402       return;
403     }
404     //
405     bIsConformState=Standard_True;
406     aIt.Initialize(aLP);
407     for (iCnt=0; aIt.More(); aIt.Next(), ++iCnt) {
408       if (myNbPntsMax) {
409         if (iCnt > myNbPntsMax) {
410           break;
411         }
412       }
413       //
414       const gp_Pnt& aP=aIt.Value();
415       //
416       myClsf->SetPnt(aP);
417       myClsf->Perform();
418       iErr=myClsf->ErrorStatus();
419       if (iErr) {
420         myErrorStatus=40; // point can not be classified
421         return;
422       }
423       //
424       aSt=myClsf->State();
425       //
426       bIsToBreak=aSC.AppendState(aSt);
427       if (bIsToBreak) {
428         break;
429       }
430     }
431     //
432     aSt=aSC.State();
433     //
434     bIsConformState=GEOMAlgo_SurfaceTools::IsConformState(aSt, myState);
435     if (myShapeType==TopAbs_EDGE) {
436       if (bIsConformState) {
437         myMSS.Add(aE, aSt);
438       }
439     }
440     else if (bIsConformState || aSt==TopAbs_ON) {
441       myMSS.Add(aE, aSt);
442     }
443   } //  for (i=1; i<=aNb; ++i) next edge
444 }
445 //=======================================================================
446 //function : ProcessFaces
447 //purpose  :
448 //=======================================================================
449 void GEOMAlgo_FinderShapeOn2::ProcessFaces()
450 {
451   myErrorStatus=0;
452   //
453   Standard_Boolean bIsConformState, bIsToBreak, bCanBeON;
454   Standard_Integer i, aNbF, iCnt, iErr;
455   TopAbs_State aSt;
456   TopTools_IndexedMapOfShape aM;
457   TopExp_Explorer aExp;
458   GEOMAlgo_ListIteratorOfListOfPnt aIt;
459   //
460   TopExp::MapShapes(myShape, TopAbs_FACE, aM);
461   aNbF=aM.Extent();
462   for (i=1; i<=aNbF; ++i) {
463     GEOMAlgo_StateCollector aSC;
464     GEOMAlgo_ListOfPnt aLP;
465     //
466     const TopoDS_Face& aF=TopoDS::Face(aM(i));
467     //
468     if (myState==GEOMAlgo_ST_ON) {
469       Handle(Geom_Surface) aS;
470       //
471       aS=BRep_Tool::Surface(aF);
472       bCanBeON=myClsf->CanBeON(aS);
473       if(!bCanBeON) {
474         continue;
475       }
476     }
477     //
478     aExp.Init(aF, TopAbs_EDGE);
479     for (; aExp.More(); aExp.Next()) {
480       const TopoDS_Shape& aE=aExp.Current();
481       bIsConformState=myMSS.Contains(aE);
482       if (!bIsConformState) {
483         break;// edge has non-conformed state
484       }
485       else {
486         aSt=myMSS.FindFromKey(aE);
487         aSC.AppendState(aSt);
488       }
489     }
490     //
491     if (!bIsConformState) {
492       continue; // edge has non-conformed state,skip face
493     }
494     //
495     InnerPoints(aF, aLP);
496     if (myErrorStatus) {
497       return;
498     }
499     //
500     bIsConformState=Standard_True;
501     aIt.Initialize(aLP);
502     for (iCnt=0; aIt.More(); aIt.Next(), ++iCnt) {
503       if (myNbPntsMax) {
504         if (iCnt > myNbPntsMax) {
505           break;
506         }
507       }
508       //
509       const gp_Pnt& aP=aIt.Value();
510       //
511       myClsf->SetPnt(aP);
512       myClsf->Perform();
513       iErr=myClsf->ErrorStatus();
514       if (iErr) {
515         myErrorStatus=40; // point can not be classified
516         return;
517       }
518       //
519       aSt=myClsf->State();
520       //
521       bIsToBreak=aSC.AppendState(aSt);
522       if (bIsToBreak) {
523         break;
524       }
525     }
526     //
527     aSt=aSC.State();
528     //
529     bIsConformState=GEOMAlgo_SurfaceTools::IsConformState(aSt, myState);
530     if (myShapeType==TopAbs_FACE) {
531       if (bIsConformState) {
532         myMSS.Add(aF, aSt);
533       }
534     }
535     else if (bIsConformState || aSt==TopAbs_ON) {
536       myMSS.Add(aF, aSt);
537     }
538   }//  for (i=1; i<=aNb; ++i) next face
539 }
540 //=======================================================================
541 //function : ProcessSolids
542 //purpose  :
543 //=======================================================================
544 void GEOMAlgo_FinderShapeOn2::ProcessSolids()
545 {
546   myErrorStatus=0;
547   //
548   Standard_Boolean bIsConformState;
549   Standard_Integer i, aNbS, j, aNbF;
550   TopTools_IndexedMapOfShape aM, aMF;
551   TopAbs_State aSt;
552   //
553   TopExp::MapShapes(myShape, TopAbs_SOLID, aM);
554   aNbS=aM.Extent();
555   for (i=1; i<=aNbS; ++i) {
556     GEOMAlgo_StateCollector aSC;
557     //
558     const TopoDS_Shape& aSd=aM(i);
559     aMF.Clear();
560     TopExp::MapShapes(aSd, TopAbs_FACE, aMF);
561     aNbF=aMF.Extent();
562     for (j=1; j<=aNbF; ++j) {
563       const TopoDS_Shape& aF=aMF(j);
564       bIsConformState=myMSS.Contains(aF);
565       if (!bIsConformState) {
566         break;// face has non-conformed state
567       }
568       else {
569         aSt=myMSS.FindFromKey(aF);
570         aSC.AppendState(aSt);
571       }
572     }
573     //
574     if (!bIsConformState) {
575       continue; // face has non-conformed state,skip solid
576     }
577     //
578     aSt=aSC.State();
579     //
580     bIsConformState=GEOMAlgo_SurfaceTools::IsConformState(aSt, myState);
581     if (bIsConformState) {
582       myMSS.Add(aSd, aSt);
583     }
584   }
585 }
586 //
587 //=======================================================================
588 //function : InnerPoints
589 //purpose  :
590 //=======================================================================
591 void GEOMAlgo_FinderShapeOn2::InnerPoints(const TopoDS_Face& aF,
592                                           GEOMAlgo_ListOfPnt& aLP)
593 {
594   Standard_Integer j, j1, j2, k, n[4], aNbLinks, aNx, aNb, iCnt;//, aNbMax, *pIds;
595   TopLoc_Location aLoc;
596   Handle(Poly_Triangulation) aTRF;
597   TColStd_MapOfInteger aMBN;
598   GEOMAlgo_DataMapOfPassKeyInteger aMPKI;
599   GEOMAlgo_DataMapIteratorOfDataMapOfPassKeyInteger aIt;
600   gp_Pnt aP, aP1, aP2;
601   // 
602   myErrorStatus=0;
603   //
604   aLP.Clear();
605   //
606   aTRF=BRep_Tool::Triangulation(aF, aLoc);
607   if (aTRF.IsNull()) {
608     if (!BuildTriangulation(aF)) {
609       myWarningStatus=20; // no triangulation found
610       return;
611     }
612     aTRF=BRep_Tool::Triangulation(aF, aLoc);
613   }
614   //
615   const gp_Trsf& aTrsf=aLoc.Transformation();
616   const Poly_Array1OfTriangle& aTrs=aTRF->Triangles();
617   const TColgp_Array1OfPnt& aNodes=aTRF->Nodes();
618   //
619   // map link/nbtriangles
620   j1=aTrs.Lower();
621   j2=aTrs.Upper();
622   for (j=j1; j<=j2; ++j) {
623     const Poly_Triangle& aTr=aTrs(j);
624     aTr.Get(n[0], n[1], n[2]);
625     n[3]=n[0];
626     for (k=0; k<3; ++k) {
627       GEOMAlgo_PassKey aPK;
628       //
629       aPK.SetIds(n[k], n[k+1]);
630       if (aMPKI.IsBound(aPK)) {
631         Standard_Integer& iCntX=aMPKI.ChangeFind(aPK);
632         ++iCntX;
633       }
634       else {
635         aMPKI.Bind(aPK, 1);
636       }
637     }
638   }
639   //
640   // boundary nodes aMBN
641   aNbLinks=aMPKI.Extent();
642   aIt.Initialize(aMPKI);
643   for (; aIt.More(); aIt.Next()) {
644     iCnt=aIt.Value();
645     if (iCnt==1) {
646       const GEOMAlgo_PassKey& aPK=aIt.Key();
647       aNx=(Standard_Integer)aPK.Id(1);
648       aMBN.Add(aNx);
649       aNx=(Standard_Integer)aPK.Id(2);
650       aMBN.Add(aNx);
651       
652     }
653   }
654   //
655   // inner nodes=all_nodes - boundary_nodes
656   j1=aNodes.Lower();
657   j2=aNodes.Upper();
658   for (j=j1; j<=j2; ++j) {
659     if (!aMBN.Contains(j)) {
660       aP=aNodes(j).Transformed(aTrsf);
661       aLP.Append(aP);
662     }
663   }
664   //
665   aNb=aLP.Extent();
666   //
667   //modified by NIZNHY-PKV Mon Sep 24 08:42:32 2012f
668   if (!aNb && myNbPntsMin) {    // A
669     Standard_Boolean bIsDone, bHasFirstPoint, bHasSecondPoint;
670     Standard_Integer i, aNb, aIx, /*iErr, */aNbDomains;
671     Standard_Real aUMin, aUMax, aVMin, aVMax, dU, aUx, aVx, aV1, aV2;
672     gp_Pnt aPx;
673     gp_Dir2d aD2D (0., 1.);
674     gp_Pnt2d aP2D;
675     Handle(Geom2d_Line) aL2D;
676     Handle(Geom_Surface) aS;
677     TopoDS_Face aFF;
678     //
679     aFF=aF;
680     aFF.Orientation (TopAbs_FORWARD);
681     //
682     Geom2dHatch_Hatcher& aHatcher=myContext->Hatcher(aFF);
683     //
684     aS=BRep_Tool::Surface(aFF);
685     BRepTools::UVBounds(aFF, aUMin, aUMax, aVMin, aVMax);
686     //
687     aNb=myNbPntsMin+1;
688     dU=(aUMax-aUMin)/aNb;
689     for (i=1; i<aNb; ++i) {
690       aUx=aUMin+i*dU;
691       aP2D.SetCoord(aUx, 0.);
692       aL2D=new Geom2d_Line (aP2D, aD2D);
693       Geom2dAdaptor_Curve aHCur(aL2D);
694       //
695       aHatcher.ClrHatchings();
696       aIx=aHatcher.AddHatching(aHCur);
697       //
698       aHatcher.Trim(aIx);
699       bIsDone=aHatcher.TrimDone(aIx);
700       if (!bIsDone) {
701         myErrorStatus=42;
702         return;
703       }
704       //
705       aHatcher.ComputeDomains(aIx);
706       bIsDone=aHatcher.IsDone(aIx);
707       if (!bIsDone) {
708         continue;
709       }
710       //
711       aNbDomains=aHatcher.NbDomains(aIx);
712       for (j=1; j<=aNbDomains; ++j) {
713         const HatchGen_Domain& aDomain=aHatcher.Domain (aIx, j) ; 
714         // 1
715         bHasFirstPoint=aDomain.HasFirstPoint();
716         bHasSecondPoint=aDomain.HasSecondPoint();
717         if (!bHasFirstPoint || !bHasSecondPoint) {
718           continue;
719         }
720         // 2
721         aV1=aDomain.FirstPoint().Parameter();
722         aV2=aDomain.SecondPoint().Parameter();
723         aVx=IntTools_Tools::IntermediatePoint(aV1, aV2);
724         // 3
725         aS->D0(aUx, aVx, aPx);
726         aLP.Append(aPx);
727         break;
728       }
729     }// for (i=1; i<aNb; ++i) {
730   }// if (!aNb && myNbPntsMin) {
731 }
732 //=======================================================================
733 //function : InnerPoints
734 //purpose  :
735 //=======================================================================
736 void GEOMAlgo_FinderShapeOn2::InnerPoints(const TopoDS_Edge& aE,
737                                           GEOMAlgo_ListOfPnt& aLP)
738 {
739   myErrorStatus=0;
740   //
741   Standard_Integer j, aNbNodes, aIndex, aNb;
742   Handle(Poly_PolygonOnTriangulation) aPTE;
743   Handle(Poly_Triangulation) aTRE;
744   TopLoc_Location aLoc;
745   gp_Pnt aP;
746   //
747   aLP.Clear();
748   BRep_Tool::PolygonOnTriangulation(aE, aPTE, aTRE, aLoc);
749   if (aTRE.IsNull() || aPTE.IsNull()) {
750     Handle(Poly_Polygon3D) aPE = BRep_Tool::Polygon3D(aE, aLoc);
751     if (aPE.IsNull()) {
752       if (!BuildTriangulation(aE)) {
753         myErrorStatus=20; // no triangulation found
754         return;
755       }
756       aPE = BRep_Tool::Polygon3D(aE, aLoc);
757     }
758     const gp_Trsf& aTrsf=aLoc.Transformation();
759     const TColgp_Array1OfPnt& aNodes=aPE->Nodes();
760     //
761     aNbNodes=aPE->NbNodes();
762     Standard_Integer low = aNodes.Lower(), up = aNodes.Upper();
763     for (j=low+1; j<up; ++j) {
764       aP=aNodes(j).Transformed(aTrsf);
765       aLP.Append(aP);
766     }
767   }
768   else {
769     const gp_Trsf& aTrsf=aLoc.Transformation();
770     const TColgp_Array1OfPnt& aNodes=aTRE->Nodes();
771     //
772     aNbNodes=aPTE->NbNodes();
773     const TColStd_Array1OfInteger& aInds=aPTE->Nodes();
774     for (j=2; j<aNbNodes; ++j) {
775       aIndex=aInds(j);
776       aP=aNodes(aIndex).Transformed(aTrsf);
777       aLP.Append(aP);
778     }
779   }
780   //
781   aNb=aLP.Extent();
782   if (!aNb && myNbPntsMin) {
783     // try to fill it yourself
784     InnerPoints(aE, myNbPntsMin, aLP);
785     aNb=aLP.Extent();
786   }
787 }
788 //=======================================================================
789 //function : InnerPoints
790 //purpose  :
791 //=======================================================================
792 void GEOMAlgo_FinderShapeOn2::InnerPoints(const TopoDS_Edge& aE,
793                                           const Standard_Integer aNbPntsMin,
794                                           GEOMAlgo_ListOfPnt& aLP)
795 {
796   // try to fill it yourself
797   Standard_Boolean bInf1, bInf2;
798   Standard_Integer j, aNbT;
799   Standard_Real dT, aT, aT1, aT2;
800   gp_Pnt aP;
801   Handle(Geom_Curve) aC3D;
802   //
803   aC3D=BRep_Tool::Curve(aE, aT1, aT2);
804   if (aC3D.IsNull()) {
805     return;
806   }
807   //
808   bInf1=Precision::IsNegativeInfinite(aT1);
809   bInf2=Precision::IsPositiveInfinite(aT2);
810   if (bInf1 || bInf2) {
811     return;
812   }
813   //
814   aNbT=myNbPntsMin+1;
815   dT=(aT2-aT1)/aNbT;
816   for (j=1; j<=aNbPntsMin; ++j) {
817     aT=aT1+j*dT;
818     aC3D->D0(aT, aP);
819     aLP.Append(aP);
820   }
821 }
822
823 //=======================================================================
824 //function : BuildTriangulation
825 //purpose  :
826 //=======================================================================
827 Standard_Boolean
828   GEOMAlgo_FinderShapeOn2::BuildTriangulation (const TopoDS_Shape& theShape)
829 {
830   // calculate deflection
831   Standard_Real aDeviationCoefficient = 0.001;
832
833   Bnd_Box B;
834   BRepBndLib::Add(theShape, B);
835   Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
836   B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
837
838   Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
839   Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
840   Standard_Real aHLRAngle = 0.349066;
841
842   // build triangulation
843   BRepMesh_IncrementalMesh Inc (theShape, aDeflection, Standard_False, aHLRAngle);
844
845   // check triangulation
846   bool isTriangulation = true;
847
848   TopExp_Explorer exp (theShape, TopAbs_FACE);
849   if (exp.More())
850   {
851     TopLoc_Location aTopLoc;
852     Handle(Poly_Triangulation) aTRF;
853     aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
854     if (aTRF.IsNull()) {
855       isTriangulation = false;
856     }
857   }
858   else // no faces, try edges
859   {
860     TopExp_Explorer expe (theShape, TopAbs_EDGE);
861     if (!expe.More()) {
862       isTriangulation = false;
863     }
864     else {
865       TopLoc_Location aLoc;
866       Handle(Poly_Polygon3D) aPE = BRep_Tool::Polygon3D(TopoDS::Edge(expe.Current()), aLoc);
867       if (aPE.IsNull()) {
868         isTriangulation = false;
869       }
870     }
871   }
872
873   return isTriangulation;
874 }
875
876 //
877 // myErrorStatus :
878 //
879 // 10 -myClsf=NULL
880 // 11 -myShape=NULL
881 // 12 -unallowed type of sub-shapes
882 // 13 -unallowed state
883 // 15 -unallowed surface type
884 // 20- no triangulation found
885 // 30- can not obtain the line from the link
886 // 40- point can not be classified
887 // 41- invalid data for classifier
888 // 42- can not compute hatching