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