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