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