0022807: Loading of STEP entities in model during reading of STEP file requires redun...
[occt.git] / src / AIS / AIS_IdenticRelation.cxx
CommitLineData
7fd59977 1// File: AIS_IdenticRelation.cxx
2// Created: Mon Mar 3 17:21:37 1997
3// Author: Jean-Pierre COMBE
4// <jpr>
5
6
7#include <Standard_NotImplemented.hxx>
8
9#include <AIS_IdenticRelation.ixx>
10
11#include <AIS.hxx>
12#include <AIS_Shape.hxx>
13#include <AIS_Drawer.hxx>
14
15#include <BRep_Tool.hxx>
16
17#include <DsgPrs_IdenticPresentation.hxx>
18
19#include <ElCLib.hxx>
20
21#include <Geom_Circle.hxx>
22#include <Geom_Line.hxx>
23#include <Geom_Plane.hxx>
24#include <Geom_TrimmedCurve.hxx>
25
26#include <Precision.hxx>
27
28#include <Prs3d_Drawer.hxx>
29#include <Prs3d_LineAspect.hxx>
30
31#include <Select3D_SensitiveCurve.hxx>
32#include <Select3D_SensitiveSegment.hxx>
33#include <SelectMgr_EntityOwner.hxx>
34
35#include <TColStd_ListIteratorOfListOfTransient.hxx>
36
37#include <StdPrs_WFDeflectionShape.hxx>
38
39#include <TCollection_ExtendedString.hxx>
40
41#include <TopAbs.hxx>
42#include <TopExp.hxx>
43#include <TopoDS.hxx>
44#include <TopoDS_Edge.hxx>
45#include <TopoDS_Vertex.hxx>
46#include <TopoDS_Wire.hxx>
47#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
48#include <TopTools_ListIteratorOfListOfShape.hxx>
49
50#include <gp_Dir.hxx>
51#include <gp_Pnt.hxx>
52#include <gp_Pln.hxx>
53#include <gp_Vec.hxx>
54
55// jfa 15/10/2000
56#include <Geom_Ellipse.hxx>
57#include <GeomAPI_ProjectPointOnCurve.hxx>
58
59static Standard_Real Modulo2PI(const Standard_Real ANGLE)
60{
61 if ( ANGLE < 0 ) return Modulo2PI(ANGLE + 2*PI);
62 else if ( ANGLE >= 2*PI ) return Modulo2PI(ANGLE - 2*PI);
63 return ANGLE;
64}
65
66static Standard_Boolean IsEqual2PI(const Standard_Real angle1,
67 const Standard_Real angle2, const Standard_Real precision)
68{
69 Standard_Real diff = Abs(angle1-angle2);
70 if ( diff < precision ) return Standard_True;
71 else if ( Abs(diff-2*PI) < precision ) return Standard_True;
72 return Standard_False;
73}
74// jfa 15/10/2000 end
75
76//=======================================================================
77//function : AIS_Sort
78//purpose : sort an array of parameters <tab1> in increasing order
79// updates <tab2> and <tab3> according to <tab1>
80//=======================================================================
81static void AIS_Sort(Standard_Real tab1[4],
82 gp_Pnt tab2[4],
83 Standard_Integer tab3[4])
84{
85 Standard_Boolean found = Standard_True;
86 Standard_Real cur; gp_Pnt cur1; Standard_Integer cur2;
87
88 while (found) {
89 found = Standard_False;
90 for (Standard_Integer i=0; i< 3; i++) {
91 if (tab1[i+1] < tab1[i]) {
92 found = Standard_True;
93 cur = tab1[i]; cur1 = tab2[i]; cur2 = tab3[i];
94 tab1[i] = tab1[i+1]; tab2[i] = tab2[i+1]; tab3[i] = tab3[i+1];
95 tab1[i+1] = cur; tab2[i+1] = cur1; tab3[i+1] = cur2;
96 }
97 }
98 }
99}
100
101//=======================================================================
102//function : ConnectedEdges
103//purpose :
104//=======================================================================
105static Standard_Boolean ConnectedEdges(const TopoDS_Wire& WIRE,
106 const TopoDS_Vertex& V,
107 TopoDS_Edge& E1,
108 TopoDS_Edge& E2)
109{
110 TopTools_IndexedDataMapOfShapeListOfShape vertexMap;
111 TopExp::MapShapesAndAncestors (WIRE,TopAbs_VERTEX,TopAbs_EDGE,vertexMap);
112
113 Standard_Boolean found(Standard_False);
114 TopoDS_Vertex theVertex;
115 for (Standard_Integer i=1; i<=vertexMap.Extent() && !found; i++) {
116 if (vertexMap.FindKey(i).IsSame(V)) {
117 theVertex = TopoDS::Vertex(vertexMap.FindKey(i));
118 found = Standard_True;
119 }
120 }
121 if (!found) {
122 E1.Nullify();
123 E2.Nullify();
124 return Standard_False;
125 }
126
127 TopTools_ListIteratorOfListOfShape iterator(vertexMap.FindFromKey(theVertex));
128 if (iterator.More()) {
129 E1 = TopoDS::Edge(iterator.Value());
130 iterator.Next();
131 }
132 else {
133 E1.Nullify();
134 return Standard_False;
135 }
136
137 if (iterator.More()) {
138 E2 = TopoDS::Edge(iterator.Value());
139 iterator.Next();
140 }
141 else {
142 E2.Nullify();
143 return Standard_False;
144 }
145
146 if (iterator.More()) {
147 E1.Nullify();
148 E2.Nullify();
149 return Standard_False;
150 }
151 return Standard_True;
152}
153
154// jfa 16/10/2000
155//=======================================================================
156//function : ComputeAttach
157//purpose : Compute a point on the arc of <thecirc>
158// between <aFAttach> and <aSAttach>
159// corresponding to <aPosition>
160// Returns result into <aPosition>
161// Note : This function is to be used only in the case of circles.
162// The <aPosition> parameter is in/out.
163//=======================================================================
164static Standard_Boolean ComputeAttach(const gp_Circ& thecirc,
165 const gp_Pnt& aFAttach,
166 const gp_Pnt& aSAttach,
167 gp_Pnt& aPosition)
168{
169 gp_Pnt curpos = aPosition;
170
171 // Case of confusion between the current position and the center
172 // of the circle -> we move the current position
173 Standard_Real confusion (Precision::Confusion());
174 gp_Pnt aCenter = thecirc.Location();
175 if ( aCenter.Distance(curpos) <= confusion )
176 {
177 gp_Vec vprec(aCenter, aFAttach);
178 vprec.Normalize();
179 curpos.Translate(vprec*1e-5);
180 }
181
182 Standard_Real pcurpos = ElCLib::Parameter(thecirc,curpos);
183 Standard_Real pFAttach = ElCLib::Parameter(thecirc,aFAttach);
184 Standard_Real pSAttach = ElCLib::Parameter(thecirc,aSAttach);
185
186 Standard_Real pSAttachM = pSAttach;
187 Standard_Real deltap = pSAttachM - pFAttach;
188 if ( deltap < 0 )
189 {
190 deltap += 2*Standard_PI;
191 pSAttachM += 2*Standard_PI;
192 }
193 pSAttachM -= pFAttach;
194
195 Standard_Real pmiddleout = pSAttachM/2.0 + Standard_PI;
196
197 Standard_Real pcurpos1 = pcurpos;
198 // define where curpos lays
199 if ( pcurpos1 < pFAttach )
200 {
201 pcurpos1 = pcurpos1 + 2*Standard_PI - pFAttach;
202 if ( pcurpos1 > pSAttachM ) // out
203 {
204 if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
205 else pcurpos = pSAttach;
206 }
207 }
208 else if ( pcurpos1 > (pFAttach + deltap) ) // out
209 {
210 pcurpos1 -= pFAttach;
211 if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
212 else pcurpos = pSAttach;
213 }
214
215 aPosition = ElCLib::Value(pcurpos,thecirc);
216 return Standard_True;
217}
218
219//=======================================================================
220//function : ComputeAttach
221//purpose : Compute a point on the arc of ellipse <theEll>
222// between <aFAttach> and <aSAttach>
223// corresponding to <aPosition>
224// Returns result into <aPosition>
225// Note : This function is to be used only in the case of ellipses.
226// The <aPosition> parameter is in/out.
227//=======================================================================
228static Standard_Boolean ComputeAttach(const gp_Elips& theEll,
229 const gp_Pnt& aFAttach,
230 const gp_Pnt& aSAttach,
231 gp_Pnt& aPosition)
232{
233 gp_Pnt curpos = aPosition;
234
235 // Case of confusion between the current position and the center
236 // of the circle -> we move the current position
237 Standard_Real confusion (Precision::Confusion());
238 gp_Pnt aCenter = theEll.Location();
239 if ( aCenter.Distance(curpos) <= confusion )
240 {
241 gp_Vec vprec(aCenter, aFAttach);
242 vprec.Normalize();
243 curpos.Translate(vprec*1e-5);
244 }
245
246// for ellipses it's not good Standard_Real pcurpos = ElCLib::Parameter(theEll,curpos);
247 Handle(Geom_Ellipse) theEllg = new Geom_Ellipse(theEll);
248 GeomAPI_ProjectPointOnCurve aProj (curpos, theEllg);
249 Standard_Real pcurpos = aProj.LowerDistanceParameter();
250
251 Standard_Real pFAttach = ElCLib::Parameter(theEll,aFAttach);
252 Standard_Real pSAttach = ElCLib::Parameter(theEll,aSAttach);
253
254 Standard_Real pSAttachM = pSAttach;
255 Standard_Real deltap = pSAttachM - pFAttach;
256 if ( deltap < 0 )
257 {
258 deltap += 2*Standard_PI;
259 pSAttachM += 2*Standard_PI;
260 }
261 pSAttachM -= pFAttach;
262
263 Standard_Real pmiddleout = pSAttachM/2.0 + Standard_PI;
264
265 Standard_Real pcurpos1 = pcurpos;
266 // define where curpos lays
267 if ( pcurpos1 < pFAttach )
268 {
269 pcurpos1 = pcurpos1 + 2*Standard_PI - pFAttach;
270 if ( pcurpos1 > pSAttachM ) // out
271 {
272 if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
273 else pcurpos = pSAttach;
274 }
275 }
276 else if ( pcurpos1 > (pFAttach + deltap) ) // out
277 {
278 pcurpos1 -= pFAttach;
279 if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
280 else pcurpos = pSAttach;
281 }
282
283 aPosition = ElCLib::Value(pcurpos,theEll);
284 return Standard_True;
285}
286// jfa 16/10/2000 end
287
288//=======================================================================
289//function : AIS_IdenticRelation
290//purpose :
291//=======================================================================
292AIS_IdenticRelation::AIS_IdenticRelation(const TopoDS_Shape& FirstShape,
293 const TopoDS_Shape& SecondShape,
294 const Handle(Geom_Plane)& aPlane)
295 :isCircle(Standard_False)
296{
297 myFShape = FirstShape;
298 mySShape = SecondShape;
299 myPlane = aPlane;
300}
301
302//=======================================================================
303//function : Compute
304//purpose :
305//=======================================================================
306void AIS_IdenticRelation::Compute(const Handle(PrsMgr_PresentationManager3d)&,
307 const Handle(Prs3d_Presentation)& aprs,
308 const Standard_Integer)
309{
310 aprs->Clear();
311
312 switch ( myFShape.ShapeType() ) {
313
314 case TopAbs_VERTEX:
315 {
316 switch ( mySShape.ShapeType() ) {
317 case TopAbs_VERTEX:
318 {
319 ComputeTwoVerticesPresentation(aprs);
320 }
321 break;
322 case TopAbs_EDGE:
323 {
324 ComputeOneEdgeOVertexPresentation(aprs);
325 }
326 break;
327 default:
328 break;
329 }
330 }
331 break;
332
333 case TopAbs_EDGE:
334 {
335 switch ( mySShape.ShapeType() ) {
336 case TopAbs_VERTEX:
337 {
338 ComputeOneEdgeOVertexPresentation(aprs);
339 }
340 break;
341 case TopAbs_EDGE:
342 {
343 ComputeTwoEdgesPresentation(aprs);
344 }
345 break;
346 default:
347 break;
348 }
349 }
350 break;
351 default: break;
352 }
353}
354
355//=======================================================================
356//function : Compute
357//purpose :
358//=======================================================================
359void AIS_IdenticRelation::Compute(const Handle(Prs3d_Projector)& aProjector,
360 const Handle(Prs3d_Presentation)& aPresentation)
361{
362// Standard_NotImplemented::Raise("AIS_IdenticRelation::Compute(const Handle(Prs3d_Projector)&,const Handle(Prs3d_Presentation)&)");
363 PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ;
364}
365
366//=======================================================================
367//function : Compute
368//purpose :
369//=======================================================================
370void AIS_IdenticRelation::Compute(const Handle(PrsMgr_PresentationManager2d)& aPresentationManager2d,
371 const Handle(Graphic2d_GraphicObject)& aGraphicObject,
372 const Standard_Integer anInteger)
373{
374// Standard_NotImplemented::Raise("AIS_IdenticRelation::Compute(const Handle(PrsMgr_PresentationManager2d)&,const Handle(Graphic2d_GraphicObject)&,const Standard_Integer)");
375 PrsMgr_PresentableObject::Compute( aPresentationManager2d ,aGraphicObject,anInteger) ;
376}
377
378void AIS_IdenticRelation::Compute(const Handle_Prs3d_Projector& aProjector, const Handle_Geom_Transformation& aTransformation, const Handle_Prs3d_Presentation& aPresentation)
379{
380// Standard_NotImplemented::Raise("AIS_IdenticRelation::Compute(const Handle_Prs3d_Projector&, const Handle_Geom_Transformation&, const Handle_Prs3d_Presentation&)");
381 PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
382}
383
384//=======================================================================
385//function : ComputeSelection
386//purpose : function used to compute the selection associated to the
387// "identic" presentation
388// note : if we are in the case of lines, we create a segment between
389// myFAttach and mySAttach. In the case of Circles, we create
81bba717 390// an arc of circle between the sames points. We Add a segment
7fd59977 391// to link Position to its projection on the curve described
392// before.
393//=======================================================================
394
395void AIS_IdenticRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
396 const Standard_Integer)
397{
398 Handle(SelectMgr_EntityOwner) own = new SelectMgr_EntityOwner(this,7);
399
400 Handle(Select3D_SensitiveSegment) seg;
401 // attachement point of the segment linking position to the curve
402 gp_Pnt attach;
403 Standard_Real confusion (Precision::Confusion());
404
405 if ( myFAttach.IsEqual(mySAttach, confusion) )
406 {
407 attach = myFAttach;
408 }
409 else
410 {
411// jfa 24/10/2000
412 if ( myFShape.ShapeType() == TopAbs_EDGE )
413 {
414 Handle(Geom_Curve) curv1,curv2;
415 gp_Pnt firstp1,lastp1,firstp2,lastp2;
416 Standard_Boolean isInfinite1,isInfinite2;
417 Handle(Geom_Curve) extCurv;
418 if ( !AIS::ComputeGeometry(TopoDS::Edge(myFShape),TopoDS::Edge(mySShape),
419 myExtShape,curv1,curv2,
420 firstp1,lastp1,firstp2,lastp2,
421 extCurv,isInfinite1,isInfinite2,myPlane) ) return;
422
423 if ( isCircle ) // case of Circles
424 {
425 Handle(Geom_Circle) thecirc = (Handle(Geom_Circle)&) curv1;
426 Standard_Real udeb = ElCLib::Parameter(thecirc->Circ(),myFAttach);
427 Standard_Real ufin = ElCLib::Parameter(thecirc->Circ(),mySAttach);
428 Handle(Geom_TrimmedCurve) thecu = new Geom_TrimmedCurve(thecirc,udeb,ufin);
429
430 Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own, thecu);
431 aSelection->Add(scurv);
432
433 attach = myPosition;
434 ComputeAttach(thecirc->Circ(),myFAttach,mySAttach,attach);
435 }
436 else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Ellipse)) ) // case of ellipses
437 {
438 Handle(Geom_Ellipse) theEll = (Handle(Geom_Ellipse)&) curv1;
439
440 Standard_Real udeb = ElCLib::Parameter(theEll->Elips(),myFAttach);
441 Standard_Real ufin = ElCLib::Parameter(theEll->Elips(),mySAttach);
442 Handle(Geom_TrimmedCurve) thecu = new Geom_TrimmedCurve(theEll,udeb,ufin);
443
444 Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own, thecu);
445 aSelection->Add(scurv);
446
447 attach = myPosition;
448 ComputeAttach(theEll->Elips(),myFAttach,mySAttach,attach);
449 }
450 else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Line)) ) // case of Lines
451 {
452 seg = new Select3D_SensitiveSegment(own, myFAttach, mySAttach);
453 aSelection->Add(seg);
454
81bba717 455 //attach = projection of Position() on the curve;
7fd59977 456 gp_Vec v1 (myFAttach, mySAttach);
457 gp_Vec v2 (myFAttach, myPosition);
458 if ( v1.IsParallel(v2, Precision::Angular()) )
459 {
460 attach = mySAttach;
461 }
462 else
463 {
464 gp_Lin ll (myFAttach, gp_Dir(v1));
465 attach = ElCLib::Value(ElCLib::Parameter(ll,myPosition), ll);
466 }
467 }
468 else return;
469 }
470// else if ( myFShape.ShapeType() == TopAbs_VERTEX )
471// {
472// }
473// jfa 24/10/2000 end
474 }
475
476 // Creation of the segment linking the attachement point with the
477 // position
478 if ( !attach.IsEqual(myPosition, confusion) )
479 {
480 seg = new Select3D_SensitiveSegment(own, attach, myPosition);
481 aSelection->Add(seg);
482 }
483}
484
485//=======================================================================
486//function : ComputeTwoEdgesPresentation
487//purpose :
488//=======================================================================
489void AIS_IdenticRelation::ComputeTwoEdgesPresentation(const Handle(Prs3d_Presentation)& aPrs)
490{
491 Handle(Geom_Curve) curv1,curv2;
492 gp_Pnt firstp1,lastp1,firstp2,lastp2;
493 Standard_Boolean isInfinite1,isInfinite2;
494
495 Handle(Geom_Curve) extCurv;
496 if (!AIS::ComputeGeometry(TopoDS::Edge(myFShape),
497 TopoDS::Edge(mySShape),
498 myExtShape,
499 curv1,
500 curv2,
501 firstp1,
502 lastp1,
503 firstp2,
504 lastp2,
505 extCurv,
506 isInfinite1,isInfinite2,
507 myPlane))
508 return;
509 aPrs->SetInfiniteState((isInfinite1 || isInfinite2) && myExtShape != 0);
510
511 // Treatement of the case of lines
512 if ( curv1->IsInstance(STANDARD_TYPE(Geom_Line)) && curv2->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
513 // we take the line curv1 like support
514 Handle(Geom_Line) thelin;
515 if (isInfinite1 && !isInfinite2) thelin = (Handle(Geom_Line)&) curv2;
516 else if (!isInfinite1 && isInfinite2) thelin = (Handle(Geom_Line)&) curv1;
517 else thelin = (Handle(Geom_Line)&) curv1;
518 ComputeTwoLinesPresentation(aPrs, thelin, firstp1, lastp1, firstp2, lastp2, isInfinite1, isInfinite2);
519 }
520
521 // Treatement of the case of circles
522 else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) && curv2->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
523 //gp_Pnt curpos;
81bba717 524 isCircle = Standard_True; // useful for ComputeSelection
7fd59977 525 const Handle(Geom_Circle)& thecirc = (Handle(Geom_Circle)&) curv1;
526 ComputeTwoCirclesPresentation(aPrs, thecirc, firstp1, lastp1, firstp2, lastp2);
527 }
528
529 // jfa 10/10/2000
530 // Treatement of the case of ellipses
531 else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Ellipse)) && curv2->IsInstance(STANDARD_TYPE(Geom_Ellipse)) )
532 {
533 const Handle(Geom_Ellipse)& theEll = (Handle(Geom_Ellipse)&) curv1;
534 ComputeTwoEllipsesPresentation(aPrs, theEll, firstp1, lastp1, firstp2, lastp2);
535 }
536 // jfa 10/10/2000 end
537 else
538 return;
539
81bba717 540 // Calculate presentation of projected edges
7fd59977 541 if ( (myExtShape != 0) && !extCurv.IsNull()) {
542 if (myExtShape == 1 )
543 ComputeProjEdgePresentation(aPrs, TopoDS::Edge(myFShape), curv1, firstp1, lastp1);
544 else
545 ComputeProjEdgePresentation(aPrs, TopoDS::Edge(mySShape), curv2, firstp2, lastp2);
546 }
547}
548
549//=======================================================================
550//function : ComputeTwoLinesPresentation
551//purpose : Compute the presentation of the 'identic' constraint
552// between two lines ( which are equal)
553//input : <thelin> : the
554// <firstp1>: first extremity of the 1st curve of the constraint
555// <lastp1> : last extremity of the 1st curve of the constraint
556// <firstp2>: first extremity of the 2nd curve of the constraint
557// <lastp2> :last extremity of the 2nd curve of the constraint
558//=======================================================================
559void AIS_IdenticRelation::ComputeTwoLinesPresentation(const Handle(Prs3d_Presentation)& aPrs,
560 const Handle(Geom_Line)& thelin,
561 gp_Pnt& firstp1,
562 gp_Pnt& lastp1,
563 gp_Pnt& firstp2,
564 gp_Pnt& lastp2,
565 const Standard_Boolean isInfinite1,
566 const Standard_Boolean isInfinite2)
567{
568 if (isInfinite1 && isInfinite2) {
569 if ( myAutomaticPosition ) {
570 myFAttach = mySAttach = thelin->Lin().Location();
571 gp_Pnt curpos;
572 gp_Pln pln(myPlane->Pln());
573 gp_Dir dir(pln.XAxis().Direction());
574 gp_Vec transvec = gp_Vec(dir)*myArrowSize;
575 curpos = myFAttach.Translated(transvec);;
576 myPosition = curpos;
577 myAutomaticPosition = Standard_True;
578 }
579 else {
580 myFAttach = mySAttach = ElCLib::Value(ElCLib::Parameter(thelin->Lin(),myPosition),thelin->Lin());
581 }
582 TCollection_ExtendedString vals(" ==");
583 DsgPrs_IdenticPresentation::Add(aPrs,
584 myDrawer,
585 vals,
586 myFAttach,
587 myPosition);
588 }
589 else {
590 // Computation of the parameters of the 4 points on the line <thelin>
591 Standard_Real pf1, pf2, pl1, pl2;
592
593 pf1 = ElCLib::Parameter(thelin->Lin(), firstp1);
594 pl1 = ElCLib::Parameter(thelin->Lin(), lastp1);
595
596 pf2 = ElCLib::Parameter(thelin->Lin(), firstp2);
597 pl2 = ElCLib::Parameter(thelin->Lin(), lastp2);
598
599 if (isInfinite1) {
600 pf1 = pf2;
601 pl1 = pl2;
602 firstp1 = firstp2;
603 lastp1 = lastp2;
604 }
605 else if (isInfinite2) {
606 pf2 = pf1;
607 pl2 = pl1;
608 firstp2 = firstp1;
609 lastp2 = lastp1;
610 }
611
612 Standard_Real tabRang1[4]; // array taht contains the parameters of the 4 points
613 // ordered by increasing abscisses.
614
615 gp_Pnt tabRang2[4]; // array containing the points corresponding to the
616 // parameters in tabRang1
617
618 Standard_Integer tabRang3[4]; // array containing the number of the curve( 1 or 2)
619 // of which belongs each point of tabRang2
620
621 // Filling of the arrays
622 tabRang1[0] = pf1; tabRang2[0] = firstp1; tabRang3[0] = 1;
623 tabRang1[1] = pf2; tabRang2[1] = firstp2; tabRang3[1] = 2;
624 tabRang1[2] = pl1; tabRang2[2] = lastp1; tabRang3[2] = 1;
625 tabRang1[3] = pl2; tabRang2[3] = lastp2; tabRang3[3] = 2;
626
627 // Sort of the array of parameters (tabRang1)
628 AIS_Sort(tabRang1, tabRang2, tabRang3);
629
630 // Computation of myFAttach and mySAttach according to the
631 // position of the 2 linear edges
632 gp_Pnt curpos;
633 gp_Pnt middle;
634
635 if ( (tabRang1[0] == tabRang1[1]) && (tabRang1[2] == tabRang1[3]) ) {
636 middle.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
637 Standard_Real pmiddle = (tabRang1[1] + tabRang1[2]) / 2.;
638 Standard_Real delta = (tabRang1[3] - tabRang1[0])/ 5.;
639 myFAttach = ElCLib::Value(pmiddle-delta, thelin->Lin());
640 mySAttach = ElCLib::Value(pmiddle+delta, thelin->Lin());
641 }
642
643 else if ( tabRang1[1] == tabRang1[2] ) {
644 middle = tabRang2[1];
645 Standard_Real delta1 = tabRang1[1] - tabRang1[0];
646 Standard_Real delta2 = tabRang1[3] - tabRang1[2];
647 if ( delta1 > delta2 ) delta1 = delta2;
648 myFAttach = ElCLib::Value(tabRang1[1]-delta1/2., thelin->Lin());
649 mySAttach = ElCLib::Value(tabRang1[1]+delta1/2., thelin->Lin());
650 }
651
652 // Case of 2 disconnected segments -> the symbol completes the gap
653 // between the 2 edges
654 //--------------------------------
655 else if ( (tabRang3[0] == tabRang3[1]) && (tabRang1[1] != tabRang1[2])) {
656 middle.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
657 myFAttach = tabRang2[1];
658 mySAttach = tabRang2[2];
659 }
660 else if ( (tabRang3[0] != tabRang3[1])
661 && (tabRang3[1] != tabRang3[2]) // Intersection
662 && (tabRang1[1] != tabRang1[2]) ) {
663 middle.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
664 myFAttach = tabRang2[1];
665 mySAttach = tabRang2[2];
666 }
667 else { // Inclusion
668 myFAttach.SetXYZ((tabRang2[0].XYZ() + tabRang2[1].XYZ())/2. );
669 mySAttach.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
670 middle.SetXYZ( (myFAttach.XYZ() + mySAttach.XYZ() )/2.);
671 }
672
673
674 if ( myAutomaticPosition ) {
675
676 gp_Vec vtrans(myFAttach, mySAttach);
677 vtrans.Normalize();
678 vtrans.Cross(gp_Vec(myPlane->Pln().Axis().Direction()));
679 vtrans *= ComputeSegSize();
680 curpos = middle.Translated(vtrans);
681 myPosition = curpos;
682 myAutomaticPosition = Standard_True;
683 }
684
685 else {
686
687 curpos = myPosition;
688 Standard_Real pcurpos = ElCLib::Parameter(thelin->Lin() ,curpos);
689 Standard_Real dist = thelin->Lin().Distance(curpos);
690 gp_Pnt proj = ElCLib::Value( pcurpos, thelin->Lin());
691 gp_Vec trans;
692 Standard_Real confusion(Precision::Confusion());
693 if ( dist >= confusion ) {
694 trans = gp_Vec(proj, curpos);
695 trans.Normalize();
696 }
697 Standard_Real pf = ElCLib::Parameter(thelin->Lin() ,myFAttach);
698 Standard_Real pl = ElCLib::Parameter(thelin->Lin() ,mySAttach);
699 if ( pcurpos <= pf ) {
700 pcurpos = pf + 1e-5;
701 curpos = ElCLib::Value( pcurpos, thelin->Lin());
702 if ( dist >= confusion ) curpos.Translate(trans*dist);
703 }
704 else if ( pcurpos >= pl ) {
705 pcurpos = pl - 1e-5;
706 curpos = ElCLib::Value( pcurpos, thelin->Lin());
707 if ( dist >= confusion ) curpos.Translate(trans*dist);
708 }
709 SetPosition(curpos);
710 }
711
712 // Display of the presentation
713 TCollection_ExtendedString vals(" ==");
714 DsgPrs_IdenticPresentation::Add(aPrs,
715 myDrawer,
716 vals,
717 myFAttach,
718 mySAttach,
719 curpos);
720 }
721}
722
723// jfa 17/10/2000
724//=======================================================================
725//function : ComputeTwoCirclesPresentation
726//purpose : Compute the presentation of the 'identic' constraint
727// between two circles ( which are equal)
728//input : <thecirc>: the circle
729// <firstp1>: first extremity of the 1st curve of the constraint
730// <lastp1> : last extremity of the 1st curve of the constraint
731// <firstp2>: first extremity of the 2nd curve of the constraint
732// <lastp2> :last extremity of the 2nd curve of the constraint
733//=======================================================================
734void AIS_IdenticRelation::ComputeTwoCirclesPresentation(const Handle(Prs3d_Presentation)& aPrs,
735 const Handle(Geom_Circle)& thecirc,
736 const gp_Pnt& firstp1,
737 const gp_Pnt& lastp1,
738 const gp_Pnt& firstp2,
739 const gp_Pnt& lastp2)
740{
741 Standard_Real confusion (Precision::Confusion());
742
743 // Searching of complete circles
744 Standard_Boolean circ1complete = (firstp1.IsEqual(lastp1, confusion));
745 Standard_Boolean circ2complete = (firstp2.IsEqual(lastp2, confusion));
746
747 myCenter = thecirc->Location();
748 Standard_Real aSegSize = thecirc->Radius()/5.0;
749 Standard_Real rad = Standard_PI/5.0;
750
751 // I. Case of 2 complete circles
752 if ( circ1complete && circ2complete )
753 {
754 if (myAutomaticPosition)
755 {
756 Standard_Real pfirst1 = ElCLib::Parameter(thecirc->Circ(), firstp1);
757 myFAttach = ElCLib::Value(Modulo2PI(pfirst1-rad), thecirc->Circ());
758 mySAttach = ElCLib::Value(Modulo2PI(pfirst1+rad), thecirc->Circ());
759
760 gp_Pnt curpos = ElCLib::Value(pfirst1,thecirc->Circ());
761 gp_Vec vtrans(myCenter, curpos);
762 vtrans.Normalize();
763 vtrans *= aSegSize;
764 curpos.Translate(vtrans);
765 myPosition = curpos;
766 }
767 else ComputeNotAutoCircPresentation(thecirc);
768 }
769
770 // II. Case of one complete circle and one arc
771 else if ( (circ1complete && !circ2complete) || (!circ1complete && circ2complete) )
772 {
773 gp_Pnt firstp, lastp;
774 if ( circ1complete && !circ2complete)
775 {
776 firstp = firstp2;
777 lastp = lastp2;
778 }
779 else
780 {
781 firstp = firstp1;
782 lastp = lastp1;
783 }
784
785 if (myAutomaticPosition)
786 {
787 ComputeAutoArcPresentation(thecirc, firstp, lastp);
788 }
789 else
790 {
791 ComputeNotAutoArcPresentation(thecirc, firstp, lastp);
792 }
793 }
794
795 // III and IV. Case of two arcs
796 else if ( !circ1complete && !circ2complete )
797 {
798 // We project all the points on the circle
799 Standard_Real pf1, pf2, pl1, pl2;
800 pf1 = ElCLib::Parameter(thecirc->Circ(), firstp1);
801 pf2 = ElCLib::Parameter(thecirc->Circ(), firstp2);
802 pl1 = ElCLib::Parameter(thecirc->Circ(), lastp1);
803 pl2 = ElCLib::Parameter(thecirc->Circ(), lastp2);
804
805 // III. Arcs with common ends
806 // III.1. First of one and last of another
807 if ( IsEqual2PI(pl1,pf2,confusion) || IsEqual2PI(pf1,pl2,confusion) )
808 {
809 gp_Pnt curpos(0.,0.,0.);
810 Standard_Real att=0.;
811 if ( IsEqual2PI(pl1,pf2,confusion) )
812 {
813 att = pl1;
814 curpos = lastp1;
815 }
816 else if ( IsEqual2PI(pf1,pl2,confusion) )
817 {
818 att = pf1;
819 curpos = firstp1;
820 }
821 Standard_Real maxrad = Min(Modulo2PI(pl1 - pf1),Modulo2PI(pl2 - pf2))*3/4;
822 if ( rad > maxrad ) rad = maxrad;
823 Standard_Real pFAttach = Modulo2PI(att - rad);
824 Standard_Real pSAttach = Modulo2PI(att + rad);
825 myFAttach = ElCLib::Value(pFAttach, thecirc->Circ());
826 mySAttach = ElCLib::Value(pSAttach, thecirc->Circ());
827 if ( myAutomaticPosition )
828 {
829 gp_Vec vtrans(myCenter,curpos);
830 vtrans.Normalize();
831 vtrans *= aSegSize;
832 curpos.Translate(vtrans);
833 myPosition = curpos;
834 }
835 }
836 // III.2. Two first or two last
837 else if ( IsEqual2PI(pf1,pf2,confusion) || IsEqual2PI(pl1,pl2,confusion) )
838 {
839 Standard_Real l1 = Modulo2PI(pl1 - pf1);
840 Standard_Real l2 = Modulo2PI(pl2 - pf2);
841 gp_Pnt firstp,lastp;
842 if ( l1 < l2 )
843 {
844 firstp = firstp1;
845 lastp = lastp1;
846 }
847 else
848 {
849 firstp = firstp2;
850 lastp = lastp2;
851 }
852
853 if ( myAutomaticPosition )
854 {
855 ComputeAutoArcPresentation(thecirc, firstp, lastp);
856 }
857 else
858 {
859 ComputeNotAutoArcPresentation(thecirc, firstp, lastp);
860 }
861 }
862 // IV. All others arcs (without common ends)
863 else
864 {
865 // order the parameters; first will be pf1
866 Standard_Real pl1m = Modulo2PI(pl1 - pf1);
867 Standard_Real pf2m = Modulo2PI(pf2 - pf1);
868 Standard_Real pl2m = Modulo2PI(pl2 - pf1);
869
870 Standard_Boolean case1 = Standard_False;
871 // 1 - not intersecting arcs
872 // 2 - intersecting arcs, but one doesn't contain another
873 // 3a - first arc contains the second one
874 // 3b - second arc contains the first one
875 // 4 - two intersections
876
877 gp_Pnt firstp, lastp;
878
879 if ( pl1m < pf2m ) // 1 or 2b or 3b
880 {
881 if ( pl1m < pl2m ) // 1 or 3b
882 {
883 if ( pl2m < pf2m ) // 3b
884 {
885 firstp = firstp1;
886 lastp = lastp1;
887 }
888 else // 1
889 {
890 case1 = Standard_True;
891 Standard_Real deltap1 = Modulo2PI(pf1 - pl2);
892 Standard_Real deltap2 = Modulo2PI(pf2 - pl1);
893 if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
894 ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
895 {
896 firstp = lastp1;
897 lastp = firstp2;
898 }
899 else // deltap1
900 {
901 firstp = lastp2;
902 lastp = firstp1;
903 }
904 }
905 }
906 else // 2b
907 {
908 firstp = firstp1;
909 lastp = lastp2;
910 }
911 }
912 else // 2a or 3a or 4
913 {
914 if ( pl1m < pl2m ) // 2a
915 {
916 firstp = firstp2;
917 lastp = lastp1;
918 }
919 else // 3a or 4
920 {
921 if ( pl2m > pf2m ) // 3a
922 {
923 firstp = firstp2;
924 lastp = lastp2;
925 }
926 else // 4
927 {
928 Standard_Real deltap1 = Modulo2PI(pl1 - pf2);
929 Standard_Real deltap2 = Modulo2PI(pl2 - pf1);
930 if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
931 ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
932 {
933 firstp = firstp1;
934 lastp = lastp2;
935 }
936 else // deltap1
937 {
938 firstp = firstp2;
939 lastp = lastp1;
940 }
941 }
942 }
943 }
944
945 if ( myAutomaticPosition )
946 {
947 ComputeAutoArcPresentation(thecirc,firstp,lastp,case1);
948 }
949 else
950 {
951 if ( case1 )
952 {
953 myFAttach = firstp;
954 mySAttach = lastp;
955 }
956 else ComputeNotAutoArcPresentation(thecirc, firstp, lastp);
957 }
958 }
959 }
960
961 // Display of the presentation
962 TCollection_ExtendedString vals(" ==");
963 gp_Pnt attach = myPosition;
964 ComputeAttach(thecirc->Circ(),myFAttach,mySAttach,attach);
965 DsgPrs_IdenticPresentation::Add(aPrs,
966 myDrawer,
967 vals,
968 myPlane->Pln().Position().Ax2(),
969 myCenter,
970 myFAttach,
971 mySAttach,
972 myPosition,
973 attach);
974}
975
976//=======================================================================
977//function : ComputeAutoArcPresentation
978//purpose : Compute the presentation of the constraint where we are
979// not in the case of dragging.
980//=======================================================================
981void AIS_IdenticRelation::ComputeAutoArcPresentation(const Handle(Geom_Circle)& thecirc,
982 const gp_Pnt& firstp,
983 const gp_Pnt& lastp,
984 const Standard_Boolean isstatic)
985{
986 Standard_Real aSegSize = thecirc->Radius()/5.0;
987 Standard_Real rad = Standard_PI/5.0;
988
989 Standard_Real pFA = ElCLib::Parameter(thecirc->Circ(),firstp);
990 Standard_Real pSA = ElCLib::Parameter(thecirc->Circ(),lastp);
991 Standard_Real maxrad = Modulo2PI(pSA - pFA)/2.0;
992
993 if ( (rad > maxrad) || isstatic ) rad = maxrad;
994 Standard_Real pmiddle = Modulo2PI(pFA + Modulo2PI(pSA - pFA)/2.0);
995
996 myFAttach = ElCLib::Value(Modulo2PI(pmiddle - rad),thecirc->Circ());
997 mySAttach = ElCLib::Value(Modulo2PI(pmiddle + rad),thecirc->Circ());
998
999 gp_Pnt curpos = ElCLib::Value(pmiddle,thecirc->Circ());
1000 gp_Vec vtrans(myCenter, curpos);
1001 vtrans.Normalize();
1002 vtrans *= aSegSize;
1003 myPosition = curpos.Translated(vtrans);
1004}
1005
1006//=======================================================================
1007//function : ComputeNotAutoCircPresentation
1008//purpose : Compute the presentation of the constraint where we are
1009// in the case of dragging.
1010// Note : This function is to be used only in the case of full circles.
1011// The symbol of the constraint moves together with arc
1012// representing the constraint around all the circle.
1013//=======================================================================
1014void AIS_IdenticRelation::ComputeNotAutoCircPresentation(const Handle(Geom_Circle)& thecirc)
1015{
1016 gp_Pnt curpos = myPosition;
1017
1018 Handle(Geom_Circle) cirNotAuto = new Geom_Circle(thecirc->Circ());
1019
1020 // Case of confusion between the current position and the center
1021 // of the circle -> we move the current position
1022 Standard_Real confusion (Precision::Confusion());
1023 if ( myCenter.Distance(curpos) <= confusion )
1024 {
1025 gp_Vec vprec(myCenter, myFAttach);
1026 vprec.Normalize();
1027 curpos.Translate(vprec*1e-5);
1028 }
1029
1030 Standard_Real rad = Standard_PI/5.0;
1031 Standard_Real pcurpos = ElCLib::Parameter(cirNotAuto->Circ(),curpos);
1032 Standard_Real pFAttach = pcurpos - rad;
1033 Standard_Real pSAttach = pcurpos + rad;
1034 myFAttach = ElCLib::Value(pFAttach,cirNotAuto->Circ());
1035 mySAttach = ElCLib::Value(pSAttach,cirNotAuto->Circ());
1036}
1037
1038//=======================================================================
1039//function : ComputeNotAutoArcPresentation
1040//purpose : Compute the presentation of the constraint where we are
1041// in the case of dragging.
1042// Note : This function is to be used only in the case of circles.
1043// The symbol of the constraint moves only between myFAttach
1044// and mySAttach.
1045//=======================================================================
1046void AIS_IdenticRelation::ComputeNotAutoArcPresentation(const Handle(Geom_Circle)& thecirc,
1047 const gp_Pnt& pntfirst,
1048 const gp_Pnt& pntlast)
1049{
1050 gp_Pnt curpos = myPosition;
1051
1052 gp_Circ cirNotAuto = thecirc->Circ();
1053
1054 Standard_Real pFPnt = ElCLib::Parameter(cirNotAuto, pntfirst);
1055 Standard_Real pSPnt = ElCLib::Parameter(cirNotAuto, pntlast);
1056 Standard_Real deltap = Modulo2PI(pSPnt - pFPnt)/2.0;
1057
1058 Standard_Real rad = Standard_PI/5;
1059 if ( deltap < rad )
1060 {
1061 myFAttach = pntfirst;
1062 mySAttach = pntlast;
1063 }
1064 else
1065 {
1066 gp_Pnt aFPnt = ElCLib::Value(Modulo2PI(pFPnt + rad), cirNotAuto);
1067 gp_Pnt aSPnt = ElCLib::Value(Modulo2PI(pSPnt - rad), cirNotAuto);
1068
1069 ComputeAttach(cirNotAuto,aFPnt,aSPnt,curpos);
1070
1071 Standard_Real pcurpos = ElCLib::Parameter(cirNotAuto,curpos);
1072 myFAttach = ElCLib::Value(pcurpos - rad, cirNotAuto);
1073 mySAttach = ElCLib::Value(pcurpos + rad, cirNotAuto);
1074 }
1075}
1076// jfa 17/10/2000 end
1077
1078// jfa 18/10/2000
1079//=======================================================================
1080//function : ComputeTwoEllipsesPresentation
1081//purpose : Compute the presentation of the 'identic' constraint
1082// between two ellipses (which are equal)
1083//input : <theEll>: the ellipse
1084// <firstp1>: first extremity of the 1st curve of the constraint
1085// <lastp1> : last extremity of the 1st curve of the constraint
1086// <firstp2>: first extremity of the 2nd curve of the constraint
1087// <lastp2> :last extremity of the 2nd curve of the constraint
1088//=======================================================================
1089void AIS_IdenticRelation::ComputeTwoEllipsesPresentation(const Handle(Prs3d_Presentation)& aPrs,
1090 const Handle(Geom_Ellipse)& theEll,
1091 const gp_Pnt& firstp1,
1092 const gp_Pnt& lastp1,
1093 const gp_Pnt& firstp2,
1094 const gp_Pnt& lastp2)
1095{
1096 Standard_Real confusion (Precision::Confusion());
1097
1098 // Searching of complete ellipses
1099 Standard_Boolean circ1complete = (firstp1.IsEqual(lastp1, confusion));
1100 Standard_Boolean circ2complete = (firstp2.IsEqual(lastp2, confusion));
1101
1102 myCenter = theEll->Location();
1103 Standard_Real aSegSize = theEll->MajorRadius()/5.0;
1104 Standard_Real rad = Standard_PI/5.0;
1105
1106 // I. Case of 2 complete ellipses
1107 if ( circ1complete && circ2complete )
1108 {
1109 if (myAutomaticPosition)
1110 {
1111 Standard_Real pfirst1 = ElCLib::Parameter(theEll->Elips(), firstp1);
1112 myFAttach = ElCLib::Value(Modulo2PI(pfirst1-rad), theEll->Elips());
1113 mySAttach = ElCLib::Value(Modulo2PI(pfirst1+rad), theEll->Elips());
1114
1115 gp_Pnt curpos = ElCLib::Value(pfirst1,theEll->Elips());
1116 gp_Vec vtrans(myCenter, curpos);
1117 vtrans.Normalize();
1118 vtrans *= aSegSize;
1119 curpos.Translate(vtrans);
1120 myPosition = curpos;
1121 }
1122 else ComputeNotAutoElipsPresentation(theEll);
1123 }
1124
1125 // II. Case of one complete circle and one arc
1126 else if ( (circ1complete && !circ2complete) || (!circ1complete && circ2complete) )
1127 {
1128 gp_Pnt firstp, lastp;
1129 if ( circ1complete && !circ2complete)
1130 {
1131 firstp = firstp2;
1132 lastp = lastp2;
1133 }
1134 else
1135 {
1136 firstp = firstp1;
1137 lastp = lastp1;
1138 }
1139
1140 if (myAutomaticPosition)
1141 {
1142 ComputeAutoArcPresentation(theEll, firstp, lastp);
1143 }
1144 else
1145 {
1146 ComputeNotAutoArcPresentation(theEll, firstp, lastp);
1147 }
1148 }
1149
1150 // III and IV. Case of two arcs
1151 else if ( !circ1complete && !circ2complete )
1152 {
1153 // We project all the points on the circle
1154 Standard_Real pf1, pf2, pl1, pl2;
1155 pf1 = ElCLib::Parameter(theEll->Elips(), firstp1);
1156 pf2 = ElCLib::Parameter(theEll->Elips(), firstp2);
1157 pl1 = ElCLib::Parameter(theEll->Elips(), lastp1);
1158 pl2 = ElCLib::Parameter(theEll->Elips(), lastp2);
1159
1160 // III. Arcs with common ends
1161 // III.1. First of one and last of another
1162 if ( IsEqual2PI(pl1,pf2,confusion) || IsEqual2PI(pf1,pl2,confusion) )
1163 {
1164 gp_Pnt curpos;
1165 Standard_Real att=0.;
1166 if ( IsEqual2PI(pl1,pf2,confusion) )
1167 {
1168 att = pl1;
1169 curpos = lastp1;
1170 }
1171 else if ( IsEqual2PI(pf1,pl2,confusion) )
1172 {
1173 att = pf1;
1174 curpos = firstp1;
1175 }
1176 Standard_Real maxrad = Min(Modulo2PI(pl1 - pf1),Modulo2PI(pl2 - pf2))*3/4;
1177 if ( rad > maxrad ) rad = maxrad;
1178 Standard_Real pFAttach = Modulo2PI(att - rad);
1179 Standard_Real pSAttach = Modulo2PI(att + rad);
1180 myFAttach = ElCLib::Value(pFAttach, theEll->Elips());
1181 mySAttach = ElCLib::Value(pSAttach, theEll->Elips());
1182 if ( myAutomaticPosition )
1183 {
1184 gp_Vec vtrans(myCenter,curpos);
1185 vtrans.Normalize();
1186 vtrans *= aSegSize;
1187 curpos.Translate(vtrans);
1188 myPosition = curpos;
1189 }
1190 }
1191 // III.2. Two first or two last
1192 else if ( IsEqual2PI(pf1,pf2,confusion) || IsEqual2PI(pl1,pl2,confusion) )
1193 {
1194 Standard_Real l1 = Modulo2PI(pl1 - pf1);
1195 Standard_Real l2 = Modulo2PI(pl2 - pf2);
1196 gp_Pnt firstp,lastp;
1197 if ( l1 < l2 )
1198 {
1199 firstp = firstp1;
1200 lastp = lastp1;
1201 }
1202 else
1203 {
1204 firstp = firstp2;
1205 lastp = lastp2;
1206 }
1207
1208 if ( myAutomaticPosition )
1209 {
1210 ComputeAutoArcPresentation(theEll, firstp, lastp);
1211 }
1212 else
1213 {
1214 ComputeNotAutoArcPresentation(theEll, firstp, lastp);
1215 }
1216 }
1217 // IV. All others arcs (without common ends)
1218 else
1219 {
1220 // order the parameters; first will be pf1
1221 Standard_Real pl1m = Modulo2PI(pl1 - pf1);
1222 Standard_Real pf2m = Modulo2PI(pf2 - pf1);
1223 Standard_Real pl2m = Modulo2PI(pl2 - pf1);
1224
1225 Standard_Boolean case1 = Standard_False;
1226 // 1 - not intersecting arcs
1227 // 2 - intersecting arcs, but one doesn't contain another
1228 // 3a - first arc contains the second one
1229 // 3b - second arc contains the first one
1230 // 4 - two intersections
1231
1232 gp_Pnt firstp, lastp;
1233
1234 if ( pl1m < pf2m ) // 1 or 2b or 3b
1235 {
1236 if ( pl1m < pl2m ) // 1 or 3b
1237 {
1238 if ( pl2m < pf2m ) // 3b
1239 {
1240 firstp = firstp1;
1241 lastp = lastp1;
1242 }
1243 else // 1
1244 {
1245 case1 = Standard_True;
1246 Standard_Real deltap1 = Modulo2PI(pf1 - pl2);
1247 Standard_Real deltap2 = Modulo2PI(pf2 - pl1);
1248 if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
1249 ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
1250 {
1251 firstp = lastp1;
1252 lastp = firstp2;
1253 }
1254 else // deltap1
1255 {
1256 firstp = lastp2;
1257 lastp = firstp1;
1258 }
1259 }
1260 }
1261 else // 2b
1262 {
1263 firstp = firstp1;
1264 lastp = lastp2;
1265 }
1266 }
1267 else // 2a or 3a or 4
1268 {
1269 if ( pl1m < pl2m ) // 2a
1270 {
1271 firstp = firstp2;
1272 lastp = lastp1;
1273 }
1274 else // 3a or 4
1275 {
1276 if ( pl2m > pf2m ) // 3a
1277 {
1278 firstp = firstp2;
1279 lastp = lastp2;
1280 }
1281 else // 4
1282 {
1283 Standard_Real deltap1 = Modulo2PI(pl1 - pf2);
1284 Standard_Real deltap2 = Modulo2PI(pl2 - pf1);
1285 if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
1286 ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
1287 {
1288 firstp = firstp1;
1289 lastp = lastp2;
1290 }
1291 else // deltap1
1292 {
1293 firstp = firstp2;
1294 lastp = lastp1;
1295 }
1296 }
1297 }
1298 }
1299
1300 if ( myAutomaticPosition )
1301 {
1302 ComputeAutoArcPresentation(theEll,firstp,lastp,case1);
1303 }
1304 else
1305 {
1306 if ( case1 )
1307 {
1308 myFAttach = firstp;
1309 mySAttach = lastp;
1310 }
1311 else ComputeNotAutoArcPresentation(theEll, firstp, lastp);
1312 }
1313 }
1314 }
1315
1316 // Display of the presentation
1317 TCollection_ExtendedString vals(" ==");
1318 gp_Pnt attach = myPosition;
1319 ComputeAttach(theEll->Elips(),myFAttach,mySAttach,attach);
1320 DsgPrs_IdenticPresentation::Add(aPrs,
1321 myDrawer,
1322 vals,
1323 theEll->Elips(),
1324 myFAttach,
1325 mySAttach,
1326 myPosition,
1327 attach);
1328}
1329
1330//=======================================================================
1331//function : ComputeAutoArcPresentation
1332//purpose : Compute the presentation of the constraint where we are
1333// not in the case of dragging.
1334//=======================================================================
1335void AIS_IdenticRelation::ComputeAutoArcPresentation(const Handle(Geom_Ellipse)& theEll,
1336 const gp_Pnt& firstp,
1337 const gp_Pnt& lastp,
1338 const Standard_Boolean isstatic)
1339{
1340 Standard_Real aSegSize = theEll->MajorRadius()/5.0;
1341 Standard_Real rad = Standard_PI/5.0;
1342
1343 gp_Elips anEll = theEll->Elips();
1344
1345 Standard_Real pFA = ElCLib::Parameter(anEll,firstp);
1346 Standard_Real pSA = ElCLib::Parameter(anEll,lastp);
1347 Standard_Real maxrad = Modulo2PI(pSA - pFA)/2.0;
1348
1349 if ( (rad > maxrad) || isstatic ) rad = maxrad;
1350 Standard_Real pmiddle = Modulo2PI(pFA + Modulo2PI(pSA - pFA)/2.0);
1351
1352 myFAttach = ElCLib::Value(Modulo2PI(pmiddle - rad),anEll);
1353 mySAttach = ElCLib::Value(Modulo2PI(pmiddle + rad),anEll);
1354
1355 gp_Pnt curpos = ElCLib::Value(pmiddle,anEll);
1356 gp_Vec vtrans(myCenter, curpos);
1357 vtrans.Normalize();
1358 vtrans *= aSegSize;
1359 myPosition = curpos.Translated(vtrans);
1360}
1361
1362//=======================================================================
1363//function : ComputeNotAutoElipsPresentation
1364//purpose : Compute the presentation of the constraint where we are
1365// in the case of dragging.
1366// Note : This function is to be used only in the case of ellipses.
1367// The symbol of the constraint moves only between myFAttach
1368// and mySAttach.
1369//=======================================================================
1370void AIS_IdenticRelation::ComputeNotAutoElipsPresentation(const Handle(Geom_Ellipse)& theEll)
1371{
1372 gp_Pnt curpos = myPosition;
1373
1374 gp_Elips anEll = theEll->Elips();
1375
1376 // Case of confusion between the current position and the center
1377 // of the ellipse -> we move the current position
1378 Standard_Real confusion (Precision::Confusion());
1379 if ( myCenter.Distance(curpos) <= confusion )
1380 {
1381 gp_Vec vprec(myCenter, myFAttach);
1382 vprec.Normalize();
1383 curpos.Translate(vprec*1e-5);
1384 }
1385
1386 Standard_Real rad = Standard_PI/5.0;
1387// Standard_Real pcurpos = ElCLib::Parameter(anEll,curpos);
1388 GeomAPI_ProjectPointOnCurve aProj (curpos, theEll);
1389 Standard_Real pcurpos = aProj.LowerDistanceParameter();
1390
1391 Standard_Real pFAttach = pcurpos - rad;
1392 Standard_Real pSAttach = pcurpos + rad;
1393 myFAttach = ElCLib::Value(pFAttach,anEll);
1394 mySAttach = ElCLib::Value(pSAttach,anEll);
1395}
1396
1397//=======================================================================
1398//function : ComputeNotAutoArcPresentation
1399//purpose : Compute the presentation of the constraint where we are
1400// in the case of dragging.
1401// Note : This function is to be used only in the case of ellipses.
1402// The symbol of the constraint moves only between myFAttach
1403// and mySAttach.
1404//=======================================================================
1405void AIS_IdenticRelation::ComputeNotAutoArcPresentation(const Handle(Geom_Ellipse)& theEll,
1406 const gp_Pnt& pntfirst,
1407 const gp_Pnt& pntlast)
1408{
1409 gp_Pnt curpos = myPosition;
1410
1411 gp_Elips anEll = theEll->Elips();
1412
1413 Standard_Real pFPnt = ElCLib::Parameter(anEll, pntfirst);
1414 Standard_Real pSPnt = ElCLib::Parameter(anEll, pntlast);
1415 Standard_Real deltap = Modulo2PI(pSPnt - pFPnt)/2.0;
1416
1417 Standard_Real rad = Standard_PI/5;
1418 if ( deltap < rad )
1419 {
1420 myFAttach = pntfirst;
1421 mySAttach = pntlast;
1422 }
1423 else
1424 {
1425 gp_Pnt aFPnt = ElCLib::Value(Modulo2PI(pFPnt + rad), anEll);
1426 gp_Pnt aSPnt = ElCLib::Value(Modulo2PI(pSPnt - rad), anEll);
1427
1428 ComputeAttach(anEll,aFPnt,aSPnt,curpos);
1429
1430// Standard_Real pcurpos = ElCLib::Parameter(anEll,curpos);
1431 GeomAPI_ProjectPointOnCurve aProj (curpos, theEll);
1432 Standard_Real pcurpos = aProj.LowerDistanceParameter();
1433
1434 myFAttach = ElCLib::Value(pcurpos - rad, anEll);
1435 mySAttach = ElCLib::Value(pcurpos + rad, anEll);
1436 }
1437}
1438// jfa 18/10/2000 end
1439
1440//=======================================================================
1441//function : ComputeTwoVerticesPresentation
1442//purpose :
1443//=======================================================================
1444void AIS_IdenticRelation::ComputeTwoVerticesPresentation(const Handle(Prs3d_Presentation)& aPrs)
1445{
1446 Standard_Boolean isOnPlane1, isOnPlane2;
1447 const TopoDS_Vertex& FVertex = TopoDS::Vertex(myFShape);
1448 const TopoDS_Vertex& SVertex = TopoDS::Vertex(mySShape);
1449
1450 AIS::ComputeGeometry(FVertex, myFAttach, myPlane, isOnPlane1);
1451 AIS::ComputeGeometry(SVertex, mySAttach, myPlane, isOnPlane2);
1452
1453 if (isOnPlane1 && isOnPlane2)
1454 myExtShape = 0;
1455 else if ( isOnPlane1 && !isOnPlane2)
1456 myExtShape = 2;
1457 else if (!isOnPlane1 && isOnPlane2)
1458 myExtShape = 1;
1459 else
1460 return ;
1461
1462
1463 // The attachement points are the points themselves that must be
1464 //identical
1465 myFAttach = BRep_Tool::Pnt(FVertex);
1466 mySAttach = myFAttach;
1467
1468 gp_Pnt curpos;
1469 if (myAutomaticPosition)
1470 {
1471 //Computation of the size of the symbol
1472 Standard_Real symbsize = ComputeSegSize();
1473 if (symbsize <= Precision::Confusion()) symbsize = 1.;
1474 symbsize*=5;
1475 // Computation of the direction of the segment of the presentation
1476 // we take the median of the edges connected to vertices
1477 gp_Dir dF, dS;
1478 gp_Dir myDir;
1479 TColStd_ListIteratorOfListOfTransient it(Users());
1480 if (it.More())
1481 {
1482 const Handle(AIS_Shape)& USER = Handle(AIS_Shape)::DownCast(it.Value());
1483 if (!USER.IsNull())
1484 {
1485 const TopoDS_Shape& SH =USER->Shape();
1486 if ( (!SH.IsNull()) && (SH.ShapeType() == TopAbs_WIRE) )
1487 {
1488 const TopoDS_Wire& WIRE = TopoDS::Wire(USER->Shape());
1489 Standard_Boolean done = ComputeDirection(WIRE,FVertex,dF);
1490 if (!done) return;
1491 done = ComputeDirection(WIRE,SVertex,dS);
1492 if (!done) return;
1493 }
1494 else return;
1495 }
1496 else return;
1497
1498 // computation of the segment direction like average
1499 // of the 2 computed directions.
1500 if ( dF.IsParallel(dS, Precision::Angular()) )
1501 {
1502 myDir = dF.Crossed(myPlane->Pln().Axis().Direction());
1503 }
1504 else
1505 {
1506 myDir.SetXYZ(dF.XYZ() + dS.XYZ());
1507 }
1508 curpos = myFAttach.Translated(gp_Vec(myDir)*symbsize) ;
1509 }
1510// jfa 11/10/2000
1511 else
1512 {
1513 curpos = myFAttach;
1514 }
1515// jfa 11/10/2000 end
1516
1517 myPosition = curpos;
1518 myAutomaticPosition = Standard_False;
1519 }
1520 else
1521 {
1522 curpos = myPosition;
1523 }
1524
1525 // Presentation computation
1526 TCollection_ExtendedString vals(" ++");
1527 DsgPrs_IdenticPresentation::Add(aPrs,
1528 myDrawer,
1529 vals,
1530 myFAttach,
1531 curpos);
81bba717 1532 // Calculate the projection of vertex
7fd59977 1533 if ( myExtShape == 1)
1534 ComputeProjVertexPresentation(aPrs,FVertex,myFAttach);
1535 else if ( myExtShape == 2)
1536 ComputeProjVertexPresentation(aPrs,SVertex,mySAttach);
1537}
1538
1539
1540
1541//=======================================================================
1542//function : ComputeSegSize
1543//purpose :
1544//=======================================================================
1545Standard_Real AIS_IdenticRelation::ComputeSegSize() const
1546{
1547 return 1.;
1548}
1549
1550//=======================================================================
1551//function : ComputeDirection
1552//purpose : Compute a direction according to the different geometric
1553// elements connected to the vertex <VERT>, in way to not have
81bba717 1554// overlap between the symbol and them.
7fd59977 1555//=======================================================================
1556Standard_Boolean AIS_IdenticRelation::ComputeDirection(const TopoDS_Wire& aWire,
1557 const TopoDS_Vertex& VERT,
1558 gp_Dir& dF) const
1559{
1560 // we take the median of the edges connected to vertices
1561 TopoDS_Edge edg1,edg2;
1562 ConnectedEdges(aWire,VERT,edg1,edg2);
1563
1564 if ( edg1.IsNull() && edg2.IsNull() ) {
1565 return Standard_False;
1566 }
1567
1568 Handle(Geom_Curve) curv1,curv2;
1569 gp_Pnt firstp1,lastp1,firstp2,lastp2;
1570
1571 // Case with 2 edges connected to the vertex <VERT>
1572 if ( !edg1.IsNull() && !edg2.IsNull() ) {
1573 if ( !AIS::ComputeGeometry(edg1,edg2,
1574 curv1,curv2,
1575 firstp1, lastp1,
1576 firstp2, lastp2,myPlane))
1577 return Standard_False;
1578
1579 gp_Dir d1, d2;
1580 if ( curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
1581 d1 = ComputeCircleDirection((Handle(Geom_Circle)&) curv1, VERT);
1582 }
1583 else if (curv1->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
1584 d1 = ComputeLineDirection((Handle(Geom_Line)&) curv1, firstp1);
1585 }
1586 else
1587 return Standard_False;
1588
1589 if ( curv2->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
1590 d2 = ComputeCircleDirection( (Handle(Geom_Circle)&) curv2, VERT);
1591 }
1592 else if (curv2->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
1593 d2 =ComputeLineDirection( (Handle(Geom_Line)&) curv2, firstp2);
1594 }
1595 else
1596 return Standard_False;
1597
1598 if ( !d1.IsParallel(d2, Precision::Angular() ))
1599 dF.SetXYZ( (d1.XYZ() + d2.XYZ())/2 );
1600 else {
1601 dF= d1.Crossed(myPlane->Pln().Axis().Direction());
1602 }
1603 }
1604
1605 // Case where <VERT> is at an extremity of a wire.
1606 else {
1607 TopoDS_Edge VEdge;
1608 if ( !edg1.IsNull() )
1609 VEdge = edg1;
1610 else if (!edg2.IsNull() )
1611 VEdge = edg2;
1612 else
1613 return Standard_False;
1614
1615 if ( !AIS::ComputeGeometry(VEdge, curv1, firstp1, lastp1) )
1616 return Standard_False;
1617 if ( curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
1618 dF = ComputeCircleDirection( (Handle(Geom_Circle)&) curv1, VERT);
1619 }
1620 else if (curv1->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
1621 dF = ComputeLineDirection( (Handle(Geom_Line)&) curv1, firstp1);
1622 }
1623 else
1624 return Standard_False;
1625 }
1626
1627 return Standard_True;
1628}
1629
1630//=======================================================================
1631//function : ComputeLineDirection
1632//purpose :
1633//=======================================================================
1634gp_Dir AIS_IdenticRelation::ComputeLineDirection(const Handle(Geom_Line)& lin,
1635 const gp_Pnt& firstP) const
1636{
1637 gp_Dir dir;
1638 dir = lin->Lin().Direction();
1639 if ( !myFAttach.IsEqual(firstP, Precision::Confusion()) )
1640 dir.Reverse();
1641 return dir;
1642}
1643
1644//=======================================================================
1645//function : ComputeCircleDirection
1646//purpose :
1647//=======================================================================
1648gp_Dir AIS_IdenticRelation::ComputeCircleDirection(const Handle(Geom_Circle)& circ,
1649 const TopoDS_Vertex& VERT) const
1650{
1651 gp_Vec V(circ->Location(),BRep_Tool::Pnt(VERT));
1652 return gp_Dir(V);
1653}
1654
1655//=======================================================================
1656//function : ComputeOneEdgeOVertexPresentation
1657//purpose :
1658//=======================================================================
1659void AIS_IdenticRelation::ComputeOneEdgeOVertexPresentation(const Handle(Prs3d_Presentation)& aPrs)
1660{
1661 TopoDS_Vertex V;
1662 TopoDS_Edge E;
1663 Standard_Integer numedge;
1664
1665 if (myFShape.ShapeType() == TopAbs_VERTEX) {
1666 V = TopoDS::Vertex(myFShape);
1667 E = TopoDS::Edge(mySShape);
81bba717 1668 numedge = 2;// edge = 2nd shape
7fd59977 1669 }
1670 else {
1671 V = TopoDS::Vertex(mySShape);
1672 E = TopoDS::Edge(myFShape);
81bba717 1673 numedge = 1; // edge = 1st shape
7fd59977 1674 }
1675 gp_Pnt ptonedge1,ptonedge2;
1676 Handle(Geom_Curve) aCurve;
1677 Handle(Geom_Curve) extCurv;
1678 Standard_Boolean isInfinite;
1679 Standard_Boolean isOnPlanEdge, isOnPlanVertex;
1680 if (!AIS::ComputeGeometry(E,aCurve,ptonedge1,ptonedge2,extCurv,isInfinite,isOnPlanEdge,myPlane))
1681 return;
1682 aPrs->SetInfiniteState(isInfinite);
1683 AIS::ComputeGeometry(V, myFAttach, myPlane, isOnPlanVertex);
1684
81bba717 1685 // only the curve can be projected
7fd59977 1686 if (!isOnPlanEdge && !isOnPlanVertex) return;
1687
1688 if (!isOnPlanEdge) {
1689 if (numedge == 1) myExtShape = 1;
1690 else myExtShape = 2;
1691 }
1692 else if (!isOnPlanVertex) {
1693 if (numedge == 1) myExtShape = 2;
1694 else myExtShape = 1;
1695 }
1696 // The attachement points are the point
1697 myFAttach = BRep_Tool::Pnt(V);
1698 mySAttach = myFAttach;
1699
1700 gp_Pnt curpos;
1701 if (myAutomaticPosition) {
1702 //Computation of the size of the symbol
1703 Standard_Real symbsize = ComputeSegSize();
1704 symbsize*=5;
1705 // Computation of the direction of the segment of the presentation
1706 // we take the median of the edges connected to vertices
1707 gp_Dir myDir;
1708 if ( aCurve->IsKind(STANDARD_TYPE(Geom_Line))) {
1709 myDir = ((Handle(Geom_Line)&) aCurve)->Lin().Direction();
1710 myDir.Cross(myPlane->Pln().Axis().Direction());
1711 }
1712 else if (aCurve->IsKind(STANDARD_TYPE(Geom_Circle))) {
1713 Handle(Geom_Circle) CIR = (Handle(Geom_Circle)&) aCurve;
1714 myDir.SetXYZ(myFAttach.XYZ() - CIR->Location().XYZ());
1715 }
1716 // jfa 10/10/2000
1717 else if (aCurve->IsKind(STANDARD_TYPE(Geom_Ellipse))) {
1718 Handle(Geom_Ellipse) CIR = (Handle(Geom_Ellipse)&) aCurve;
1719 myDir.SetXYZ(myFAttach.XYZ() - CIR->Location().XYZ());
1720 }
1721 // jfa 10/10/2000 end
1722
1723 curpos = myFAttach.Translated(gp_Vec(myDir)*symbsize) ;
1724 myPosition = curpos;
1725 myAutomaticPosition = Standard_True;
1726 }
1727 else {
1728 curpos = myPosition;
1729 }
1730
1731 // Presentation computation
1732 TCollection_ExtendedString vals(" -+-");
1733 DsgPrs_IdenticPresentation::Add(aPrs,
1734 myDrawer,
1735 vals,
1736 myFAttach,
1737 curpos);
1738 if (myExtShape != 0) {
81bba717 1739 if (!extCurv.IsNull()) { // the edge is not in the WP
7fd59977 1740 ComputeProjEdgePresentation(aPrs,E,(Handle(Geom_Line)&) aCurve,ptonedge1,ptonedge2);
1741 }
1742 }
1743}