0023663: Removing 2D viewer library
[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  : 
241 //=======================================================================
242
243 void AIS_FixRelation::Compute(const Handle_Prs3d_Projector& aProjector,
244                               const Handle_Geom_Transformation& aTransformation,
245                               const Handle_Prs3d_Presentation& aPresentation)
246 {
247 // Standard_NotImplemented::Raise("AIS_FixRelation::Compute(const Handle_Prs3d_Projector&, const Handle_Geom_Transformation&, const Handle_Prs3d_Presentation&)");
248  PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
249 }
250
251 //=======================================================================
252 //function : ComputeSelection
253 //purpose  : 
254 //=======================================================================
255
256 void AIS_FixRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection, 
257                                        const Standard_Integer)
258 {
259   Handle(SelectMgr_EntityOwner) own = new SelectMgr_EntityOwner(this,7);
260
261   // creation of segment sensible for the linked segment  
262   // of the shape fixed to symbol 'Fix'
263   Handle(Select3D_SensitiveSegment) seg;
264   seg = new Select3D_SensitiveSegment(own,
265                                       myPntAttach,
266                                       myPosition);
267   aSelection->Add(seg);
268   
269   // Creation of the sensible zone of symbol 'Fix'
270   gp_Dir norm = myPlane->Axis().Direction();
271     
272   gp_Vec dirac(myPntAttach,myPosition);
273   dirac.Normalize();
274   gp_Vec norac = dirac.Crossed(gp_Vec(norm));
275   gp_Ax1 ax(myPosition, norm);
276   norac.Rotate(ax, M_PI/8);
277
278   norac*=(myArrowSize/2);
279   gp_Pnt P1 = myPosition.Translated(norac);
280   gp_Pnt P2 = myPosition.Translated(-norac);
281   seg = new Select3D_SensitiveSegment(own,
282                                       P1,
283                                       P2);
284   aSelection->Add(seg);
285
286   norac*=0.8;
287   P1 = myPosition.Translated(norac);
288   P2 = myPosition.Translated(-norac);
289   dirac*=(myArrowSize/2);
290   gp_Pnt PF(P1.XYZ());
291   gp_Pnt PL = PF.Translated(dirac);
292   PL.Translate(norac);
293   seg = new Select3D_SensitiveSegment(own,
294                                       PF,
295                                       PL);
296   aSelection->Add(seg);
297
298
299   PF.SetXYZ(P2.XYZ());
300   PL = PF.Translated(dirac);
301   PL.Translate(norac);
302   seg = new Select3D_SensitiveSegment(own,
303                                       PF,
304                                       PL);
305   aSelection->Add(seg);
306
307   PF.SetXYZ( (P1.XYZ() + P2.XYZ()) /2 );
308   PL = PF.Translated(dirac);
309   PL.Translate(norac);
310   seg = new Select3D_SensitiveSegment(own,
311                                       PF,
312                                       PL);
313 }
314
315 //=======================================================================
316 //function : ComputeVertex
317 //purpose  : computes myPntAttach and the position of the presentation 
318 //           when you fix a vertex
319 //=======================================================================
320
321 void AIS_FixRelation::ComputeVertex(const TopoDS_Vertex& /*FixVertex*/,
322                                     gp_Pnt& curpos)
323 {
324   myPntAttach = BRep_Tool::Pnt(TopoDS::Vertex(myFShape));
325   curpos = myPosition;
326   if (myAutomaticPosition) {
327       gp_Pln pln(myPlane->Pln());
328       gp_Dir dir(pln.XAxis().Direction());
329       gp_Vec transvec = gp_Vec(dir)*myArrowSize;
330       curpos = myPntAttach.Translated(transvec);;
331       myPosition = curpos;
332       myAutomaticPosition = Standard_True;
333   }
334 }
335
336 //=======================================================================
337 //function : ComputePosition
338 //purpose  : 
339 //=======================================================================
340
341 gp_Pnt AIS_FixRelation::ComputePosition(const Handle(Geom_Curve)& curv1, 
342                                         const Handle(Geom_Curve)& curv2, 
343                                         const gp_Pnt& firstp1, 
344                                         const gp_Pnt& lastp1, 
345                                         const gp_Pnt& firstp2, 
346                                         const gp_Pnt& lastp2) const 
347 {
348   //---------------------------------------------------------
349   // calculate the point of attach
350   //---------------------------------------------------------
351   gp_Pnt curpos;
352
353   if (curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) || curv2->IsInstance(STANDARD_TYPE(Geom_Circle))) {    
354     Handle(Geom_Circle) gcirc = Handle(Geom_Circle)::DownCast(curv1);
355     if (gcirc.IsNull()) gcirc = Handle(Geom_Circle)::DownCast(curv2);
356     gp_Dir dir( gcirc->Location().XYZ() + myPntAttach.XYZ() );
357     gp_Vec transvec = gp_Vec(dir)*myArrowSize;
358     curpos = myPntAttach.Translated(transvec);    
359   }
360
361   else {
362     gp_Vec vec1(firstp1,lastp1);
363     gp_Vec vec2(firstp2,lastp2);
364     
365     if (!vec1.IsParallel(vec2, Precision::Angular()) ) {
366       gp_Dir dir;
367       Standard_Real conf =Precision::Confusion();
368       if (lastp1.IsEqual(firstp2,conf) || firstp1.IsEqual(lastp2,conf)) dir.SetXYZ(vec1.XYZ() - vec2.XYZ());
369       else dir.SetXYZ(vec1.XYZ() + vec2.XYZ());
370       gp_Vec transvec = gp_Vec(dir)*myArrowSize;
371       curpos = myPntAttach.Translated(transvec);
372     }
373     else {
374       gp_Vec crossvec = vec1.Crossed(vec2);
375       vec1.Cross(crossvec);
376       gp_Dir dir(vec1);
377       curpos = myPntAttach.Translated(gp_Vec(dir)*myArrowSize);
378     }
379   }
380
381   return curpos;
382 }
383
384 //=======================================================================
385 //function : ComputePosition
386 //purpose  : Computes the position of the "fix dimension" when the 
387 //           fixed object is a vertex which is set at the intersection
388 //           of two curves.
389 //           The "dimension" is in the "middle" of the two edges.
390 //=======================================================================
391
392 gp_Pnt AIS_FixRelation::ComputePosition(const Handle(Geom_Curve)& curv, 
393                                         const gp_Pnt& firstp, 
394                                         const gp_Pnt& lastp) const 
395 {
396   //---------------------------------------------------------
397   // calculate the point of attach
398   //---------------------------------------------------------
399   gp_Pnt curpos;
400
401   if (curv->IsKind(STANDARD_TYPE(Geom_Circle))) {
402     
403     Handle(Geom_Circle) gcirc = Handle(Geom_Circle)::DownCast(curv);
404     gp_Dir dir( gcirc->Location().XYZ() + myPntAttach.XYZ() );
405     gp_Vec transvec = gp_Vec(dir)*myArrowSize;
406     curpos = myPntAttach.Translated(transvec);
407     
408   } //if (curv->IsKind(STANDARD_TYPE(Geom_Circle))
409
410   else {
411 //    gp_Pln pln(Component()->WorkingPlane()->Plane()->GetValue()->Pln());
412     gp_Pln pln(myPlane->Pln());
413     gp_Dir NormPln = pln.Axis().Direction();
414     gp_Vec vec(firstp,lastp);
415     vec.Cross( gp_Vec(NormPln));
416     vec.Normalize();
417     gp_Vec transvec = vec*myArrowSize;
418     curpos = myPntAttach.Translated(transvec);
419     gp_Ax1 RotAx( myPntAttach, NormPln);
420     curpos.Rotate(RotAx, M_PI/10);
421   }
422
423   return curpos;
424  }
425
426 //=======================================================================
427 //function : ComputeEdge 
428 //purpose  : computes myPntAttach and the position of the presentation 
429 //           when you fix an edge
430 //=======================================================================
431
432 void AIS_FixRelation::ComputeEdge(const TopoDS_Edge& FixEdge, gp_Pnt& curpos)
433 {
434   Handle(Geom_Curve) curEdge;
435   gp_Pnt ptbeg,ptend;
436   if (!AIS::ComputeGeometry(FixEdge,curEdge,ptbeg,ptend)) return;
437
438   //---------------------------------------------------------
439   // calcul du point de positionnement du symbole 'fix'
440   //---------------------------------------------------------
441         //--> In case of a straight line
442   if (curEdge->IsKind(STANDARD_TYPE(Geom_Line))){
443     gp_Lin glin = Handle(Geom_Line)::DownCast(curEdge)->Lin();
444     Standard_Real pfirst(ElCLib::Parameter(glin,ptbeg));
445     Standard_Real plast(ElCLib::Parameter(glin,ptend));
446     ComputeLinePosition(glin, curpos, pfirst, plast);
447   }
448   
449         //--> In case of a circle
450   else if (curEdge->IsKind(STANDARD_TYPE(Geom_Circle))) {
451     gp_Circ  gcirc = Handle(Geom_Circle)::DownCast(curEdge)->Circ();
452     Standard_Real pfirst, plast;
453     BRepAdaptor_Curve cu(FixEdge);
454     pfirst = cu.FirstParameter();
455     plast = cu.LastParameter();
456     ComputeCirclePosition(gcirc, curpos, pfirst, plast);
457   }
458   
459   else
460     return;
461     
462 }
463
464 //=======================================================================
465 //function : ComputeLinePosition
466 //purpose  : compute the values of myPntAttach and the position <pos> of
467 //           the symbol when the fixed edge has a geometric support equal
468 //           to a line.
469 //=======================================================================
470
471 void AIS_FixRelation::ComputeLinePosition(const gp_Lin& glin, 
472                                           gp_Pnt& pos, 
473                                           Standard_Real& pfirst, 
474                                           Standard_Real& plast)
475 {
476   if (myAutomaticPosition) {
477     // point of attach is chosen as middle of the segment
478     myPntAttach = ElCLib::Value((pfirst+ plast)/2, glin);
479     
480     gp_Dir norm = myPlane ->Axis().Direction();
481      
482     norm.Cross(glin.Position().Direction());
483     pos = myPntAttach.Translated(gp_Vec(norm)*myArrowSize);
484     myAutomaticPosition = Standard_True;
485   } // if (myAutomaticPosition)
486
487   else {
488     pos = myPosition;
489     Standard_Real linparam = ElCLib::Parameter(glin, pos);
490
491     // case if the projection of position is located between 2 vertices
492     // de l'edge
493     if ( (linparam >= pfirst) && (linparam <= plast) )
494       myPntAttach = ElCLib::Value(linparam,glin);
495     
496     // case if the projection of Position is outside of the limits
497     // of the edge : the point closest to the projection is chosen 
498     // as the attach point
499     else {
500       Standard_Real pOnLin;
501       if (linparam > plast)
502         pOnLin = plast;
503       else
504         pOnLin = pfirst;
505       myPntAttach = ElCLib::Value(pOnLin,glin);
506       gp_Dir norm = myPlane->Axis().Direction();
507         
508       norm.Cross(glin.Position().Direction());
509       gp_Lin lsup(myPntAttach, norm);
510       Standard_Real parpos = ElCLib::Parameter(lsup,myPosition);
511       pos =  ElCLib::Value(parpos,lsup);
512     }
513
514   }
515   myPosition = pos;
516 }
517
518 //=======================================================================
519 //function : ComputeCirclePosition 
520 //purpose  : compute the values of myPntAttach and the position <pos> of
521 //           the symbol when the fixed edge has a geometric support equal
522 //           to a circle. 
523 //=======================================================================
524
525 void AIS_FixRelation::ComputeCirclePosition(
526         const gp_Circ& gcirc, 
527         gp_Pnt& pos, 
528         Standard_Real& pfirst, 
529         Standard_Real& plast)
530 {
531   // readjust parametres on the circle
532   if (plast > 2*M_PI ) {
533     Standard_Real nbtours = Floor(plast / (2*M_PI));
534     plast -= nbtours*2*M_PI;
535     pfirst -= nbtours*2*M_PI;
536   }
537
538   if (myAutomaticPosition) {
539     // the point attach is the "middle" of the segment (relatively
540     // to the parametres of start and end vertices of the edge
541     
542     Standard_Real circparam = (pfirst + plast)/2.;
543
544     if ( !InDomain(pfirst,plast,circparam)) {
545       Standard_Real otherpar = circparam + M_PI;
546       if (otherpar > 2*M_PI) otherpar -= 2*M_PI;
547       circparam = otherpar;
548     }
549
550     myPntAttach = ElCLib::Value(circparam, gcirc );
551
552     gp_Vec dir( gcirc.Location().XYZ(), myPntAttach.XYZ() );
553     dir.Normalize();
554     gp_Vec transvec = dir*myArrowSize;
555     pos = myPntAttach.Translated(transvec);
556     myPosition = pos;
557     myAutomaticPosition = Standard_True;
558   } // if (myAutomaticPosition)
559
560   else {
561     // case if the projection of myPosition is outside of 2
562     // vertices of the edge. In this case the parameter is readjusted
563     // in the valid part of the circle
564     pos = myPosition;
565
566     Standard_Real circparam = ElCLib::Parameter(gcirc, pos);
567
568     if ( !InDomain(pfirst,plast,circparam)) {
569       Standard_Real otherpar = circparam + M_PI;
570       if (otherpar > 2*M_PI) otherpar -= 2*M_PI;
571       circparam = otherpar;
572     }
573     
574     myPntAttach = ElCLib::Value(circparam,gcirc);
575   }
576 }
577
578 //=======================================================================
579 //function : ConnectedEdges
580 //purpose  : 
581 //=======================================================================
582 Standard_Boolean AIS_FixRelation::ConnectedEdges(const TopoDS_Wire& WIRE,
583                                                  const TopoDS_Vertex& V, 
584                                                  TopoDS_Edge& E1, 
585                                                  TopoDS_Edge& E2)
586 {
587   TopTools_IndexedDataMapOfShapeListOfShape  vertexMap;
588   TopExp::MapShapesAndAncestors (WIRE,TopAbs_VERTEX,TopAbs_EDGE,vertexMap);
589   
590   Standard_Boolean found(Standard_False);
591   TopoDS_Vertex theVertex;
592   for (Standard_Integer i=1; i<=vertexMap.Extent() && !found; i++) {
593     if (vertexMap.FindKey(i).IsSame(V)) {
594      theVertex = TopoDS::Vertex(vertexMap.FindKey(i));
595      found = Standard_True;
596    }
597   }
598   if (!found) {
599     E1.Nullify();
600     E2.Nullify();
601     return Standard_False;
602   }
603
604   TopTools_ListIteratorOfListOfShape iterator(vertexMap.FindFromKey(theVertex));
605   if (iterator.More()) {
606     E1 = TopoDS::Edge(iterator.Value());
607     BRepAdaptor_Curve curv(E1);
608     iterator.Next();
609   }
610   else {
611     E1.Nullify();
612     return Standard_False;
613   }
614
615   if (iterator.More()) {
616     E2 = TopoDS::Edge(iterator.Value());
617     BRepAdaptor_Curve curv(E2);
618     iterator.Next();
619   }
620   else {
621     E2.Nullify();
622     return Standard_False;
623   }
624     
625   if (iterator.More()) {
626     E1.Nullify();
627     E2.Nullify();
628     return Standard_False;
629   }
630   return Standard_True;
631 }