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