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