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