Replacing french comments by english one
[occt.git] / src / AIS / AIS_FixRelation.cxx
1 // File:        AIS_FixRelation.cdl
2 // Created:     Tue Dec  5 15:09:04 1996
3 // Author:      Flore Lantheaume/Odile Olivier
4 //              <ODL>
5
6 #define BUC60915        //GG 05/06/01 Enable to compute the requested arrow size
7 //                      if any in all dimensions.
8
9 #include <Standard_NotImplemented.hxx>
10
11 #include <AIS_FixRelation.ixx>
12
13 #include <AIS_Shape.hxx>
14
15 #include <TopAbs_ShapeEnum.hxx>
16
17 #include <SelectMgr_EntityOwner.hxx>
18 #include <Select3D_SensitiveSegment.hxx>
19
20 #include <BRep_Tool.hxx>
21 #include <BRepAdaptor_Curve.hxx>
22
23 #include <TopoDS.hxx>
24 #include <TopoDS_Edge.hxx>
25 #include <TopoDS_Vertex.hxx>
26 #include <TopoDS_Wire.hxx>
27 #include <TopExp.hxx>
28 #include <TopLoc_Location.hxx>
29 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
30 #include <TopTools_IndexedMapOfShape.hxx>
31 #include <TopTools_ListIteratorOfListOfShape.hxx>
32
33 #include <TColStd_ListIteratorOfListOfTransient.hxx>
34
35 #include <Geom_Curve.hxx>
36 #include <Geom_Line.hxx>
37 #include <Geom_Circle.hxx>
38 #include <Geom_Plane.hxx>
39
40 #include <gp_Pnt.hxx>
41 #include <gp_Vec.hxx>
42 #include <gp_Dir.hxx>
43 #include <gp_Ax1.hxx>
44 #include <gp_XYZ.hxx>
45
46 #include <ElCLib.hxx>
47 #include <ElSLib.hxx>
48
49 #include <Precision.hxx>
50
51 #include <Standard_DomainError.hxx>
52
53 #include <DsgPrs_FixPresentation.hxx>
54
55 #include <AIS.hxx>
56
57 static Standard_Boolean InDomain(const Standard_Real fpar,
58                                         const Standard_Real lpar,
59                                         const Standard_Real para) 
60 {
61   if (fpar >= 0.) {
62     return ((para >= fpar) && (para <= lpar));
63   }
64   if (para >= (fpar+2*PI)) return Standard_True;
65   if (para <= lpar) return Standard_True;
66   return Standard_False;
67 }
68
69 //=======================================================================
70 //function : Constructor
71 //purpose  : vertex Fix Relation
72 //=======================================================================
73
74 AIS_FixRelation::AIS_FixRelation(const TopoDS_Shape& aShape, 
75                                  const Handle(Geom_Plane)& aPlane, 
76                                  const TopoDS_Wire& aWire)
77 :AIS_Relation(),
78  myWire(aWire),
79  haspos(Standard_False)
80 {
81   myFShape = aShape;
82   myPlane = aPlane;
83   myAutomaticPosition = Standard_True;
84   myArrowSize = 5.;
85 }
86
87 //=======================================================================
88 //function : Constructor
89 //purpose  : vertex Fix Relation
90 //=======================================================================
91
92 AIS_FixRelation::AIS_FixRelation(const TopoDS_Shape& aShape, 
93                                  const Handle(Geom_Plane)& aPlane, 
94                                  const TopoDS_Wire& aWire, 
95                                  const gp_Pnt& aPosition, 
96                                  const Standard_Real anArrowSize)
97 :AIS_Relation(),
98  myWire(aWire),
99  haspos(Standard_False)
100 {
101   myFShape = aShape;
102   myPlane = aPlane;
103   myPosition = aPosition;
104 #ifdef BUC60915
105   SetArrowSize( anArrowSize );
106 #else
107   myArrowSize = anArrowSize;
108 #endif
109   myAutomaticPosition = Standard_False;
110 }
111
112
113 //=======================================================================
114 //function : Constructor
115 //purpose  : edge (line or circle) Fix Relation
116 //=======================================================================
117
118 AIS_FixRelation::AIS_FixRelation(const TopoDS_Shape& aShape, 
119                                  const Handle(Geom_Plane)& aPlane):
120 haspos(Standard_False)
121 {
122   myFShape = aShape;
123   myPlane = aPlane;
124   myAutomaticPosition = Standard_True;
125   myArrowSize = 5.;
126 }
127
128 //=======================================================================
129 //function : Constructor
130 //purpose  : edge (line or circle) Fix Relation
131 //=======================================================================
132
133 AIS_FixRelation::AIS_FixRelation(
134         const TopoDS_Shape& aShape, 
135         const Handle(Geom_Plane)& aPlane, 
136         const gp_Pnt& aPosition, 
137         const Standard_Real anArrowSize):
138 haspos(Standard_False)
139 {
140   myFShape = aShape;
141   myPlane = aPlane;
142   myPosition = aPosition;
143 #ifdef BUC60915
144   SetArrowSize( anArrowSize );
145 #else
146   myArrowSize = anArrowSize;
147 #endif
148   myAutomaticPosition = Standard_False;
149 }
150
151 //=======================================================================
152 //function : Wire
153 //purpose  : 
154 //=======================================================================
155
156 TopoDS_Wire AIS_FixRelation::Wire()
157 {
158   return myWire;
159 }
160
161 //=======================================================================
162 //function : SetWire
163 //purpose  : 
164 //=======================================================================
165
166 void AIS_FixRelation::SetWire(const TopoDS_Wire& aWire)
167 {
168   myWire = aWire;
169 }
170
171
172 //=======================================================================
173 //function : Compute
174 //purpose  : 
175 //=======================================================================
176
177 void AIS_FixRelation::Compute(const Handle(PrsMgr_PresentationManager3d)&, 
178                               const Handle(Prs3d_Presentation)& aPresentation, 
179                               const Standard_Integer)
180 {
181   aPresentation->Clear();
182
183   // Calculate position of the symbol and
184   // point of attach of the segment on the shape
185   gp_Pnt curpos;
186   if (myFShape.ShapeType() == TopAbs_VERTEX)
187     ComputeVertex(TopoDS::Vertex(myFShape), curpos);
188   else if (myFShape.ShapeType() == TopAbs_EDGE)
189     ComputeEdge(TopoDS::Edge(myFShape), curpos);
190
191   const gp_Dir& nor = myPlane->Axis().Direction();
192
193   
194   // calculate presentation
195   // definition of the symbol size
196 #ifdef BUC60915
197   if( !myArrowSizeIsDefined )
198 #endif
199     myArrowSize = 5.;
200
201     //creation of the presentation
202   DsgPrs_FixPresentation::Add(aPresentation,
203                               myDrawer,
204                               myPntAttach,
205                               curpos,
206                               nor,
207                               myArrowSize);
208 }
209
210 //=======================================================================
211 //function : Compute
212 //purpose  : to avoid warning
213 //=======================================================================
214
215 void AIS_FixRelation::Compute(const Handle(Prs3d_Projector)& aProjector,
216                               const Handle(Prs3d_Presentation)& aPresentation)
217 {
218 // Standard_NotImplemented::Raise("AIS_FixRelation::Compute(const Handle(Prs3d_Projector)&,const Handle(Prs3d_Presentation)&)");
219  PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ; 
220 }
221
222 //=======================================================================
223 //function : Compute
224 //purpose  : to avoid warning
225 //=======================================================================
226
227 void AIS_FixRelation::Compute(const Handle(PrsMgr_PresentationManager2d)& aPresentationManager2d,
228                               const Handle(Graphic2d_GraphicObject)& aGraphicObject,
229                               const Standard_Integer anInteger)
230 {
231 // Standard_NotImplemented::Raise("AIS_FixRelation::Compute(const Handle(PrsMgr_PresentationManager2d)&,const Handle(Graphic2d_GraphicObject)&,const Standard_Integer)");
232  PrsMgr_PresentableObject::Compute( aPresentationManager2d ,aGraphicObject,anInteger) ; 
233 }
234
235 //=======================================================================
236 //function : Compute
237 //purpose  : 
238 //=======================================================================
239
240 void AIS_FixRelation::Compute(const Handle_Prs3d_Projector& aProjector,
241                               const Handle_Geom_Transformation& aTransformation,
242                               const Handle_Prs3d_Presentation& aPresentation)
243 {
244 // Standard_NotImplemented::Raise("AIS_FixRelation::Compute(const Handle_Prs3d_Projector&, const Handle_Geom_Transformation&, const Handle_Prs3d_Presentation&)");
245  PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
246 }
247
248 //=======================================================================
249 //function : ComputeSelection
250 //purpose  : 
251 //=======================================================================
252
253 void AIS_FixRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection, 
254                                        const Standard_Integer)
255 {
256   Handle(SelectMgr_EntityOwner) own = new SelectMgr_EntityOwner(this,7);
257
258   // creation of segment sensible for the linked segment  
259   // of the shape fixed to symbol 'Fix'
260   Handle(Select3D_SensitiveSegment) seg;
261   seg = new Select3D_SensitiveSegment(own,
262                                       myPntAttach,
263                                       myPosition);
264   aSelection->Add(seg);
265   
266   // Creation of the sensible zone of symbol 'Fix'
267   gp_Dir norm = myPlane->Axis().Direction();
268     
269   gp_Vec dirac(myPntAttach,myPosition);
270   dirac.Normalize();
271   gp_Vec norac = dirac.Crossed(gp_Vec(norm));
272   gp_Ax1 ax(myPosition, norm);
273   norac.Rotate(ax, PI/8);
274
275   norac*=(myArrowSize/2);
276   gp_Pnt P1 = myPosition.Translated(norac);
277   gp_Pnt P2 = myPosition.Translated(-norac);
278   seg = new Select3D_SensitiveSegment(own,
279                                       P1,
280                                       P2);
281   aSelection->Add(seg);
282
283   norac*=0.8;
284   P1 = myPosition.Translated(norac);
285   P2 = myPosition.Translated(-norac);
286   dirac*=(myArrowSize/2);
287   gp_Pnt PF(P1.XYZ());
288   gp_Pnt PL = PF.Translated(dirac);
289   PL.Translate(norac);
290   seg = new Select3D_SensitiveSegment(own,
291                                       PF,
292                                       PL);
293   aSelection->Add(seg);
294
295
296   PF.SetXYZ(P2.XYZ());
297   PL = PF.Translated(dirac);
298   PL.Translate(norac);
299   seg = new Select3D_SensitiveSegment(own,
300                                       PF,
301                                       PL);
302   aSelection->Add(seg);
303
304   PF.SetXYZ( (P1.XYZ() + P2.XYZ()) /2 );
305   PL = PF.Translated(dirac);
306   PL.Translate(norac);
307   seg = new Select3D_SensitiveSegment(own,
308                                       PF,
309                                       PL);
310 }
311
312 //=======================================================================
313 //function : ComputeVertex
314 //purpose  : computes myPntAttach and the position of the presentation 
315 //           when you fix a vertex
316 //=======================================================================
317
318 void AIS_FixRelation::ComputeVertex(const TopoDS_Vertex& /*FixVertex*/,
319                                     gp_Pnt& curpos)
320 {
321   myPntAttach = BRep_Tool::Pnt(TopoDS::Vertex(myFShape));
322   curpos = myPosition;
323   if (myAutomaticPosition) {
324       gp_Pln pln(myPlane->Pln());
325       gp_Dir dir(pln.XAxis().Direction());
326       gp_Vec transvec = gp_Vec(dir)*myArrowSize;
327       curpos = myPntAttach.Translated(transvec);;
328       myPosition = curpos;
329       myAutomaticPosition = Standard_True;
330   }
331 }
332
333 //=======================================================================
334 //function : ComputePosition
335 //purpose  : 
336 //=======================================================================
337
338 gp_Pnt AIS_FixRelation::ComputePosition(const Handle(Geom_Curve)& curv1, 
339                                         const Handle(Geom_Curve)& curv2, 
340                                         const gp_Pnt& firstp1, 
341                                         const gp_Pnt& lastp1, 
342                                         const gp_Pnt& firstp2, 
343                                         const gp_Pnt& lastp2) const 
344 {
345   //---------------------------------------------------------
346   // calculate the point of attach
347   //---------------------------------------------------------
348   gp_Pnt curpos;
349
350   if (curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) || curv2->IsInstance(STANDARD_TYPE(Geom_Circle))) {    
351     Handle(Geom_Circle) gcirc = Handle(Geom_Circle)::DownCast(curv1);
352     if (gcirc.IsNull()) gcirc = Handle(Geom_Circle)::DownCast(curv2);
353     gp_Dir dir( gcirc->Location().XYZ() + myPntAttach.XYZ() );
354     gp_Vec transvec = gp_Vec(dir)*myArrowSize;
355     curpos = myPntAttach.Translated(transvec);    
356   }
357
358   else {
359     gp_Vec vec1(firstp1,lastp1);
360     gp_Vec vec2(firstp2,lastp2);
361     
362     if (!vec1.IsParallel(vec2, Precision::Angular()) ) {
363       gp_Dir dir;
364       Standard_Real conf =Precision::Confusion();
365       if (lastp1.IsEqual(firstp2,conf) || firstp1.IsEqual(lastp2,conf)) dir.SetXYZ(vec1.XYZ() - vec2.XYZ());
366       else dir.SetXYZ(vec1.XYZ() + vec2.XYZ());
367       gp_Vec transvec = gp_Vec(dir)*myArrowSize;
368       curpos = myPntAttach.Translated(transvec);
369     }
370     else {
371       gp_Vec crossvec = vec1.Crossed(vec2);
372       vec1.Cross(crossvec);
373       gp_Dir dir(vec1);
374       curpos = myPntAttach.Translated(gp_Vec(dir)*myArrowSize);
375     }
376   }
377
378   return curpos;
379 }
380
381 //=======================================================================
382 //function : ComputePosition
383 //purpose  : Computes the position of the "fix dimension" when the 
384 //           fixed object is a vertex which is set at the intersection
385 //           of two curves.
386 //           The "dimension" is in the "middle" of the two edges.
387 //=======================================================================
388
389 gp_Pnt AIS_FixRelation::ComputePosition(const Handle(Geom_Curve)& curv, 
390                                         const gp_Pnt& firstp, 
391                                         const gp_Pnt& lastp) const 
392 {
393   //---------------------------------------------------------
394   // calculate the point of attach
395   //---------------------------------------------------------
396   gp_Pnt curpos;
397
398   if (curv->IsKind(STANDARD_TYPE(Geom_Circle))) {
399     
400     Handle(Geom_Circle) gcirc = Handle(Geom_Circle)::DownCast(curv);
401     gp_Dir dir( gcirc->Location().XYZ() + myPntAttach.XYZ() );
402     gp_Vec transvec = gp_Vec(dir)*myArrowSize;
403     curpos = myPntAttach.Translated(transvec);
404     
405   } //if (curv->IsKind(STANDARD_TYPE(Geom_Circle))
406
407   else {
408 //    gp_Pln pln(Component()->WorkingPlane()->Plane()->GetValue()->Pln());
409     gp_Pln pln(myPlane->Pln());
410     gp_Dir NormPln = pln.Axis().Direction();
411     gp_Vec vec(firstp,lastp);
412     vec.Cross( gp_Vec(NormPln));
413     vec.Normalize();
414     gp_Vec transvec = vec*myArrowSize;
415     curpos = myPntAttach.Translated(transvec);
416     gp_Ax1 RotAx( myPntAttach, NormPln);
417     curpos.Rotate(RotAx, PI/10);
418   }
419
420   return curpos;
421  }
422
423 //=======================================================================
424 //function : ComputeEdge 
425 //purpose  : computes myPntAttach and the position of the presentation 
426 //           when you fix an edge
427 //=======================================================================
428
429 void AIS_FixRelation::ComputeEdge(const TopoDS_Edge& FixEdge, gp_Pnt& curpos)
430 {
431   Handle(Geom_Curve) curEdge;
432   gp_Pnt ptbeg,ptend;
433   if (!AIS::ComputeGeometry(FixEdge,curEdge,ptbeg,ptend)) return;
434
435   //---------------------------------------------------------
436   // calcul du point de positionnement du symbole 'fix'
437   //---------------------------------------------------------
438         //--> In case of a straight line
439   if (curEdge->IsKind(STANDARD_TYPE(Geom_Line))){
440     gp_Lin glin = Handle(Geom_Line)::DownCast(curEdge)->Lin();
441     Standard_Real pfirst(ElCLib::Parameter(glin,ptbeg));
442     Standard_Real plast(ElCLib::Parameter(glin,ptend));
443     ComputeLinePosition(glin, curpos, pfirst, plast);
444   }
445   
446         //--> In case of a circle
447   else if (curEdge->IsKind(STANDARD_TYPE(Geom_Circle))) {
448     gp_Circ  gcirc = Handle(Geom_Circle)::DownCast(curEdge)->Circ();
449     Standard_Real pfirst, plast;
450     BRepAdaptor_Curve cu(FixEdge);
451     pfirst = cu.FirstParameter();
452     plast = cu.LastParameter();
453     ComputeCirclePosition(gcirc, curpos, pfirst, plast);
454   }
455   
456   else
457     return;
458     
459 }
460
461 //=======================================================================
462 //function : ComputeLinePosition
463 //purpose  : compute the values of myPntAttach and the position <pos> of
464 //           the symbol when the fixed edge has a geometric support equal
465 //           to a line.
466 //=======================================================================
467
468 void AIS_FixRelation::ComputeLinePosition(const gp_Lin& glin, 
469                                           gp_Pnt& pos, 
470                                           Standard_Real& pfirst, 
471                                           Standard_Real& plast)
472 {
473   if (myAutomaticPosition) {
474     // point of attach is chosen as middle of the segment
475     myPntAttach = ElCLib::Value((pfirst+ plast)/2, glin);
476     
477     gp_Dir norm = myPlane ->Axis().Direction();
478      
479     norm.Cross(glin.Position().Direction());
480     pos = myPntAttach.Translated(gp_Vec(norm)*myArrowSize);
481     myAutomaticPosition = Standard_True;
482   } // if (myAutomaticPosition)
483
484   else {
485     pos = myPosition;
486     Standard_Real linparam = ElCLib::Parameter(glin, pos);
487
488     // case if the projection of position is located between 2 vertices
489     // de l'edge
490     if ( (linparam >= pfirst) && (linparam <= plast) )
491       myPntAttach = ElCLib::Value(linparam,glin);
492     
493     // case if the projection of Position is outside of the limits
494     // of the edge : the point closest to the projection is chosen 
495     // as the attach point
496     else {
497       Standard_Real pOnLin;
498       if (linparam > plast)
499         pOnLin = plast;
500       else
501         pOnLin = pfirst;
502       myPntAttach = ElCLib::Value(pOnLin,glin);
503       gp_Dir norm = myPlane->Axis().Direction();
504         
505       norm.Cross(glin.Position().Direction());
506       gp_Lin lsup(myPntAttach, norm);
507       Standard_Real parpos = ElCLib::Parameter(lsup,myPosition);
508       pos =  ElCLib::Value(parpos,lsup);
509     }
510
511   }
512   myPosition = pos;
513 }
514
515 //=======================================================================
516 //function : ComputeCirclePosition 
517 //purpose  : compute the values of myPntAttach and the position <pos> of
518 //           the symbol when the fixed edge has a geometric support equal
519 //           to a circle. 
520 //=======================================================================
521
522 void AIS_FixRelation::ComputeCirclePosition(
523         const gp_Circ& gcirc, 
524         gp_Pnt& pos, 
525         Standard_Real& pfirst, 
526         Standard_Real& plast)
527 {
528   // readjust parametres on the circle
529   if (plast > 2*PI ) {
530     Standard_Real nbtours = Floor(plast / (2*PI));
531     plast -= nbtours*2*PI;
532     pfirst -= nbtours*2*PI;
533   }
534
535   if (myAutomaticPosition) {
536     // the point attach is the "middle" of the segment (relatively
537     // to the parametres of start and end vertices of the edge
538     
539     Standard_Real circparam = (pfirst + plast)/2.;
540
541     if ( !InDomain(pfirst,plast,circparam)) {
542       Standard_Real otherpar = circparam + PI;
543       if (otherpar > 2*PI) otherpar -= 2*PI;
544       circparam = otherpar;
545     }
546
547     myPntAttach = ElCLib::Value(circparam, gcirc );
548
549     gp_Vec dir( gcirc.Location().XYZ(), myPntAttach.XYZ() );
550     dir.Normalize();
551     gp_Vec transvec = dir*myArrowSize;
552     pos = myPntAttach.Translated(transvec);
553     myPosition = pos;
554     myAutomaticPosition = Standard_True;
555   } // if (myAutomaticPosition)
556
557   else {
558     // case if the projection of myPosition is outside of 2
559     // vertices of the edge. In this case the parameter is readjusted
560     // in the valid part of the circle
561     pos = myPosition;
562
563     Standard_Real circparam = ElCLib::Parameter(gcirc, pos);
564
565     if ( !InDomain(pfirst,plast,circparam)) {
566       Standard_Real otherpar = circparam + PI;
567       if (otherpar > 2*PI) otherpar -= 2*PI;
568       circparam = otherpar;
569     }
570     
571     myPntAttach = ElCLib::Value(circparam,gcirc);
572   }
573 }
574
575 //=======================================================================
576 //function : ConnectedEdges
577 //purpose  : 
578 //=======================================================================
579 Standard_Boolean AIS_FixRelation::ConnectedEdges(const TopoDS_Wire& WIRE,
580                                                  const TopoDS_Vertex& V, 
581                                                  TopoDS_Edge& E1, 
582                                                  TopoDS_Edge& E2)
583 {
584   TopTools_IndexedDataMapOfShapeListOfShape  vertexMap;
585   TopExp::MapShapesAndAncestors (WIRE,TopAbs_VERTEX,TopAbs_EDGE,vertexMap);
586   
587   Standard_Boolean found(Standard_False);
588   TopoDS_Vertex theVertex;
589   for (Standard_Integer i=1; i<=vertexMap.Extent() && !found; i++) {
590     if (vertexMap.FindKey(i).IsSame(V)) {
591      theVertex = TopoDS::Vertex(vertexMap.FindKey(i));
592      found = Standard_True;
593    }
594   }
595   if (!found) {
596     E1.Nullify();
597     E2.Nullify();
598     return Standard_False;
599   }
600
601   TopTools_ListIteratorOfListOfShape iterator(vertexMap.FindFromKey(theVertex));
602   if (iterator.More()) {
603     E1 = TopoDS::Edge(iterator.Value());
604     BRepAdaptor_Curve curv(E1);
605     iterator.Next();
606   }
607   else {
608     E1.Nullify();
609     return Standard_False;
610   }
611
612   if (iterator.More()) {
613     E2 = TopoDS::Edge(iterator.Value());
614     BRepAdaptor_Curve curv(E2);
615     iterator.Next();
616   }
617   else {
618     E2.Nullify();
619     return Standard_False;
620   }
621     
622   if (iterator.More()) {
623     E1.Nullify();
624     E2.Nullify();
625     return Standard_False;
626   }
627   return Standard_True;
628 }